How to concat a column value based on id - c#

I have a table like this in C# from a dataset
COL1 COL2 COL3 COL4 COL5
1000 APPLE 50 92 TESTING
1000 APPLE 50 92 ALPHA
1000 APPLE 50 92 BETA
1000 APPLE 50 92 OMEGA
2000 ORANGE 60 90 DELTA
2000 ORANGE 60 90 TEST
2000 ORANGE 60 90 SLEEP
I need result like this
COL1 COL2 COL3 COL4 COL5
1000 APPLE 50 92 TESTINGAPHABETAOMEGA
2000 ORANGE 60 90 DELTASLEEPTEST
How to achieve this ?
I strucked after this line
var result = from row in dataTable.AsEnumerable()
group row by row.Field<int>("COL1") into grp
select new
{
COL1= grp.Key,
Count = grp.Count()
};

I dont think you can do that with LINQ, but heres a little subroutine that will work for you.
var _rowlist = table.AsEnumerable().OrderBy(x => x.Field<Int32>("COL1")).ThenBy(x => x.Field<string>("COL2")).ThenBy(x => x.Field<string>("COL3")).ThenBy(x => x.Field<string>("COL4")).ToList();
DataTable _newtable = table.Clone();
string oldrowid = "";
foreach (DataRow _indrow in _rowlist)
{
if (!oldrowid.Equals(_indrow["COL1"].ToString()))
{
oldrowid = _indrow["COL1"].ToString();
DataRow _newrow = _newtable.NewRow();
_newrow["COL1"] = _indrow["COL1"].ToString();
_newrow["COL2"] = _indrow["COL2"].ToString();
_newrow["COL3"] = _indrow["COL3"].ToString();
_newrow["COL4"] = _indrow["COL4"].ToString();
_newrow["COL5"] = _indrow["COL5"].ToString();
_newtable.Rows.Add(_newrow);
}
else
{
Int32 _id = Int32.Parse(_indrow["COL1"].ToString());
DataRow _row = _newtable.AsEnumerable().Where(a => a.Field<Int32>("COL1") == _id).SingleOrDefault();
int Index = _newtable.Rows.IndexOf(_row);
_row["COL5"] += "," + _indrow["COL5"].ToString();
}
}
//_newtable contains what you want

Try this:
var result =
from row in dataTable.AsEnumerable()
let COL1 = row.Field<int>("COL1")
let COL2 = row.Field<string>("COL2")
let COL3 = row.Field<int>("COL3")
let COL4 = row.Field<int>("COL4")
let COL5 = row.Field<string>("COL5")
group COL5 by new { COL1, COL2, COL3, COL4, } into grp
select new
{
COL1 = grp.Key.COL1,
COL2 = grp.Key.COL2,
COL3 = grp.Key.COL3,
COL4 = grp.Key.COL4,
COL5 = String.Join("", grp),
};

var result = from row in dt.AsEnumerable()
group row by row.Field<int>("COL1") into grp
let firstCols = grp.First()
let lastCells = string.Join("", grp.Select(x => x[4]).ToArray())
select new object[] { firstCols[0], firstCols[1], firstCols[2], firstCols[3], lastCells };
var dtResult = dt.Clone();
foreach (var item in result )
{
dtResult.Rows.Add(item);
}

Related

Linq into clause returning only columns from joined table

I joined a 2 data tables based on the EMP column and used copytodatatable, however when i load the new datatable into datagridview it only shows the joined columns(salarydt) from the query, why is this??
var collection = from p in dt.AsEnumerable()
join q in salaryDT.AsEnumerable() on p.Field<int>("Emp") equals q.Field<int>("Emp1") into UP
from t in UP
select t;
DataTable resultdt = new DataTable();
dt = collection.CopyToDataTable();
DataTable itself is perfectly geared to merging itself with another data table, using its, well, Merge method. Here's a litte example:
var dt1 = new DataTable("a");
dt1.Columns.Add("ID", typeof(int));
dt1.Columns.Add("Item1", typeof(int));
dt1.PrimaryKey = new[] { dt1.Columns[0] };
var dt2 = new DataTable("a");
dt2.Columns.Add("ID", typeof(int));
dt2.Columns.Add("Item2", typeof(int));
dt2.PrimaryKey = new[] { dt2.Columns[0] };
for (int i = 0; i < 10; i++)
{
dt1.Rows.Add(new object[] { i, i });
dt2.Rows.Add(new object[] { i, i + 10 });
}
dt1.Merge(dt2);
Now dt1 has three columns, ID, Item1, and Item2.
ID Item1 Item2
0 0 10
1 1 11
2 2 12
3 3 13
4 4 14
5 5 15
6 6 16
7 7 17
8 8 18
9 9 19
Maybe what you should to do is just return a custom list of items:
Option 1
var data = new Employee[] { new Employee { Id = 1, Name = "John Doe" } };
var data2 = new Salary[] { new Salary { Id = 1, Wage = "$ 50,000.00" } };
var collection = from p in data
join q in data2 on p.Id equals q.Id
select new { Id = p.Id, Name = p.Name, Wage = q.Wage };
Please check the example: link
Option 2
var data = new Employee[] { new Employee { Id = 1, Name = "John Doe" } };
var data2 = new Salary[] { new Salary { Id = 1, Wage = "$ 50,000.00" } };
var collection = from p in data
join q in data2 on p.Id equals q.Id
select new { p, q };

How to loop and update SQL table summing any existing values

Please i need your help on this module part of my program. i have 2 tables, TableA which has "code,description,value" and TableB which has "code, values" example below :
TableA
code description value
-----------------------------
CD1 BOOKS
CD2 BREADS
CD3 PHONES
CD4 FISH
TableB
code value1 value2 value3 value4
--------------------------------------
cd1 12 21 10 21
cd2 9 10 10 11
cd3 19 11 29 13
cd4 10 12 22 12
the idea is to update TableA with the Values of TableB where TableA.code=TableB.code but if their are values in TableA then Update content of TableA Value field by adding the new values to the old value field where TableB.code = TableA.code. i have written the following code but it's only updating one row, below is my code :
DataTable dt = GetDatafromDatabase(); //===== returns a DataTable
string SQLT = "SELECT * FROM tbl_TempReport";
if (cn.State == ConnectionState.Closed) {cn.Open(); }
SqlCommand cmdT = new SqlCommand(SQLT, cn);
while (rt.Read())
{
// For each row, print the values of each column.
foreach (DataColumn column in dt.Columns)
{
foreach (DataRow row in dt.Rows)
{
colname = column.ColumnName.ToString();
string m_Code = rt["code"].ToString();
if (m_Code == colname) {
if (m_Code == colname && mValue > 0) { mValue += Convert.ToInt32(row[column].ToString()); } else { mValue = Convert.ToInt32(row[column].ToString()); }
//============ insert into tbl_TempReport to match the appropriate column
string SQLP = "UPDATE tbl_TempReport SET VALUEP = #VALUEP WHERE code = #code";
SqlCommand cmdp = new SqlCommand(SQLP, cn);
cmdp.Parameters.AddWithValue("#VALUEP", SqlDbType.Int).Value = mValue;
cmdp.Parameters.AddWithValue("#code", SqlDbType.NVarChar).Value = rt["code"].ToString();
cmdp.ExecuteNonQuery();
}
}
}
}
i need your help to achieve this. Thank you
If I understand the question, this can be done in a single update statement, without any loops:
UPDATE a
SET value = b.value1 + b.value2 + b.value3 + b.value4 + COALESCE(value, 0)
FROM TableA a
INNER JOIN TableB b ON(a.code = b.code)

Datatable Group by and sum one column

I have this datatable:
RadkyData.Columns.Add("ČísloDokladuDodavatele", typeof(string));
RadkyData.Columns.Add("Množství", typeof(string));
RadkyData.Columns.Add("NákupníCena", typeof(string));
RadkyData.Columns.Add("PřepočtováJednotka", typeof(string));
RadkyData.Columns.Add("Přepočtovýkoeficient",
Just group the rows by Col1, Col2,Col3 and Sum() up Col4
var input = new[] {
new { Col1 =1, Col2= 2, Col3 = 1, Col4 = 1.5m},
new { Col1 =1, Col2= 1, Col3 = 1, Col4 = 1.8m},
new { Col1 =1, Col2= 2, Col3 = 1, Col4 = 2.5m},
new { Col1 =1, Col2 =1, Col3 = 1, Col4 = 3m},
new { Col1 =3, Col2 =1, Col3 = 4, Col4= 5m}
};
var result = input.GroupBy(x => new { x.Col1, x.Col2, x.Col3 })
.Select(x => new
{
Col1 = x.Key.Col1,
Col2 = x.Key.Col2,
Col3 = x.Key.Col3,
Col4 = x.Sum(y => y.Col4)
});
You could do this using Linq.
table.AsEnumerable()
.Select(r=>new
{
c1=r.Field<int>("col1"),
c2 =r.Field<int>("col2"),
c3 =r.Field<int>("col3"),
c4 =r.Field<double>("col4")
})
.GroupBy(g=> new {g.c1, g.c2, g.c3})
.Select(x=> new {
col1 = x.Key.c1,
col2 = x.Key.c2,
col3 = x.Key.c3,
Sum = x.Sum(s=>s.c4)
});
Check this Demo
Output:
{ col1 = 1, col2 = 2, col3 = 1, Sum = 4 }
{ col1 = 1, col2 = 1, col3 = 1, Sum = 4.8 }
{ col1 = 3, col2 = 1, col3 = 4, Sum = 5 }
I think this should work
mytable.Columns.Add("col4",GetType(Integer),"Col1+Col2+Col3");

SELECT all columns in addition to some summary columns using LINQ

Suppose there is a table with more than 20 columns: (col1, col2, ... )
If I want to display the sum of col1 and col2 as well as the other columns,
In SQL I could:
SELECT (col1+col2), * FROM table1;
But in LINQ, I have to
from tb in table1
select new
{
sum = tb.col1 + tb.col2,
col1 = tb.col1,
col2 = tb.col2,
...
};
Is there another simpler ways? Thanks.
You can extend type of tb entity by sum property and write something like:
table1
.Select(tb => new
{
Tb = tb,
Sum = tb.col1 + tb.col2
})
.Select(x =>
{
x.Tb.sum = x.Sum;
return x.Tb;
});

DataTable group the result

I want to group in Datatable by Name, LastName and the rest should be in same row. Can someone help me with it?
My DataTable:
Name LastName 1 3 2
kiki ha FF
lola mi AA
ka xe UU
kiki ha SS
I want to have DataTable group by Name:
Name LastName 1 3 2
kiki ha FF SS
lola mi AA
ka xe UU
My new code:
var result11 = from t1 in newtable.AsEnumerable()
group t1 by new { Name = t1.Field<String>("Name"), LastName = t1.Field<String>("LastName") } into grp
select new
{
Name = grp.Key.Name,
LastName = grp.Key.LastName,
//Something must be there
};
Add these lines instead of the comment (//something must be there):
C1 = String.Join(",", grp.Select(r=>r.Field<String>("1"))),
C2 = String.Join(",", grp.Select(r=>r.Field<String>("2"))),
C3 = String.Join(",", grp.Select(r=>r.Field<String>("3")))
to get three new columns on the output that aggregate values from the columns 1, 3 and 2.
If you have multiple values in one of the columns for a group, all the values will be shown and separated by comma (,).
If you are sure that there's at most one value per column per group, then you can simply do:
C1 = grp.Max(r => r.Field<String>("1")),
C3 = grp.Max(r => r.Field<String>("3")),
C2 = grp.Max(r => r.Field<String>("2"))
If you want a DataTable as result, this gives your desired result:
var lastNameGroups = from row in table1.AsEnumerable()
group row by new {
Name= row.Field<String>("Name"),
LastName = row.Field<String>("LastName")
} into LastNameGroups
select LastNameGroups;
var table2 = table1.Clone();
foreach (var lng in lastNameGroups)
{
var row = table2.Rows.Add();
row.SetField("Name", lng.Key.Name);
row.SetField("LastName", lng.Key.LastName);
var ones = lng.Where(r => !string.IsNullOrEmpty(r.Field<String>("1")));
if(ones.Any())
row.SetField("1", ones.First().Field<String>("1"));
var twos = lng.Where(r => !string.IsNullOrEmpty(r.Field<String>("2")));
if (twos.Any())
row.SetField("2", twos.First().Field<String>("2"));
var threes = lng.Where(r => !string.IsNullOrEmpty(r.Field<String>("3")));
if (threes.Any())
row.SetField("3", threes.First().Field<String>("3"));
}

Categories