Datatable Group by and sum one column - c#

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");

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 };

Left join two datatables asp net c# LINQ

I have an issue with joining two datatables for example:
table1 table2
ID, name ID, stock
1, item1 1, blabla
1, item2 3, bla2
3, item3
After left join it should looking like this:
table3
ID, name, stock
1, item1, blabla
1, item2, blabla
3, item3, bla2
but it looks like this:
table3
ID, name, stock
1, item1,
1, item2,
3, item3,
This is mine code:
var rowDataLeftOuter = from rowLeft in dtblLeft.AsEnumerable()
join rowRight in dtblRight.AsEnumerable() on rowLeft[colToJoinOn] equals rowRight[strTempColName] into gj
from subRight in gj.DefaultIfEmpty()
select rowLeft.ItemArray.Concat((subRight == null) ? (dtblRight.NewRow().ItemArray) : subRight.ItemArray).ToArray();
foreach (object[] values in rowDataLeftOuter)
dtblResult.Rows.Add(values);
Orginal code
Not sure what the value of the columns are in the join - colToJoinOn, strTempColName However the following gives the result you're looking for:
const string columnNameId = "Id";
var dtblLeft = new DataTable();
dtblLeft.Columns.Add(new DataColumn(columnNameId, typeof(int)));
dtblLeft.Columns.Add(new DataColumn("Name", typeof(string)));
var dr1 = dtblLeft.NewRow();
dr1[columnNameId] = 1;
dr1["Name"] = "item1";
dtblLeft.Rows.Add(dr1);
var dr2 = dtblLeft.NewRow();
dr2[columnNameId] = 1;
dr2["Name"] = "item2";
dtblLeft.Rows.Add(dr2);
var dr3 = dtblLeft.NewRow();
dr3[columnNameId] = 3;
dr3["Name"] = "item3";
dtblLeft.Rows.Add(dr3);
var dtblRight = new DataTable();
dtblRight.Columns.Add(new DataColumn(columnNameId, typeof(int)));
dtblRight.Columns.Add(new DataColumn("Stock", typeof(string)));
var dr4 = dtblRight.NewRow();
dr4[columnNameId] = 1;
dr4["Stock"] = "blabla";
dtblRight.Rows.Add(dr4);
var dr5 = dtblRight.NewRow();
dr5[columnNameId] = 3;
dr5["Stock"] = "bla2";
dtblRight.Rows.Add(dr5);
var dtblResult = new DataTable();
dtblResult.Columns.Add(new DataColumn(columnNameId, typeof(int)));
dtblResult.Columns.Add(new DataColumn("Name", typeof(string)));
dtblResult.Columns.Add(new DataColumn("Stock", typeof(string)));
var result = from rowLeft in dtblLeft.AsEnumerable()
join rowRight in dtblRight.AsEnumerable() on rowLeft[columnNameId] equals rowRight[columnNameId] into gj
from subRight in gj.DefaultIfEmpty()
select dtblResult.NewRow().ItemArray = new[]
{
rowLeft[columnNameId],
rowLeft["Name"],
subRight?["Stock"] ?? ""
};
foreach (var dataRow in result)
{
dtblResult.Rows.Add(dataRow);
}

How to bind two C# datatables to one ASP: GridView [duplicate]

This question already has answers here:
Merging 2 datatables in to 1 datatable with same number of rows.
(3 answers)
Closed 5 years ago.
I have two datatables. I want to display them in one Asp: GridView side by side.
Dt1
Col1 co2
Dt2
Col3 col4
I want GridView to display as
Col1 col2 col3 col4
There is no relationship with those datatables.
My demo didn't check empty/null validation. If needed, please do.
//Create new class
public class FinalData
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
public FinalData(){}
}
//Populate your two tables into FinalData array as below
int MaxRows = dt1.Rows.Count > dt2.Rows.Count ? dt1.Rows.Count : dt2.Rows.Count;
FinalData[] fdList = new FinalData[MaxRows];
for (int i = 0; i < dt1.Rows.Count; i++)
{
FinalData[i] = new FinalData() { Col1 = dt1.Rows[i]["Col1"].ToString(), Col2 = dt1.Rows[i]["Col2"].ToString() };
}
for (int i = 0; i < dt2.Rows.Count; i++)
{
FinalData[i] = new FinalData() { Col3 = dt2.Rows[i]["Col3"].ToString(), Col4 = dt1.Rows[i]["Col4"].ToString() };
}
//Bind your gridview with fdList
YourGridview.DataSource = fdList;
YourGridView.DataBind();
You can use pivot table as follows this convert rows as columns
INSERT INTO #yourtable ([Id], [Value], [ColumnName])
VALUES
(1, 'John', 'FirstName'),
(2, '2.4', 'Amount'),
(3, 'ZH1E4A', 'PostalCode'),
(4, 'Fork', 'LastName'),
(5, '857685', 'AccountNumber');
SELECT
Firstname, Amount, PostalCode, LastName, AccountNumber
FROM
(SELECT
value, columnname
FROM
#yourtable) d
PIVOT
(MAX(value)
FOR columnname IN (Firstname, Amount, PostalCode, LastName, AccountNumber)
) piv;

Building linq query that collect records by group

scenario is simple actually but handling it in linq require more exp than I have..
There is 3 table
Table1
ID Column
1 val1
2 val2
Table2
ID Column
1 val3
2 val4
Table3
ID Column
1 val5
2 val6
I need such a query that returns;
TableResult:
Row ID Column Type
1 1 val1 table1
2 2 val2 table1
3 1 val3 table2
4 2 val4 table2
5 1 val5 table3
6 2 val6 table3
Searched on net and started like below but cant figure how handle the tricks create "type", merge records etc..
from t1 in table1
join t2 in table2 on t1.id equals t2.id
join t3 in table3 on t1.id equals t3.id
select new {...}
You've already accepted an answer, so I don't know if this is what you WANT, but it generates the output you specified in your post.
Because you have only used Id values of 1 and 2, it's unclear whether you actually want to perform a Join or just get the set of all rows into a single result.
Anyway:
struct TableStructure
{
public int Id { get; set; }
public string Column { get; set; }
}
var t1 = new List<TableStructure>() { new TableStructure { Id = 1, Column = "val1" }, new TableStructure { Id = 2, Column = "val2" } };
var t2 = new List<TableStructure>() { new TableStructure { Id = 1, Column = "val3" }, new TableStructure { Id = 2, Column = "val4" } };
var t3 = new List<TableStructure>() { new TableStructure { Id = 1, Column = "val5" }, new TableStructure { Id = 2, Column = "val6" } };
var result = ((from row1 in t1 select new { row1.Id, row1.Column, SourceTable = "table1" })
.Union(from row2 in t2 select new { row2.Id, row2.Column, SourceTable = "table2" })
.Union(from row3 in t3 select new { row3.Id, row3.Column, SourceTable = "table3" }))
.AsEnumerable().Select((row, index) => new { RowNum = index + 1, row.Id, row.Column, row.SourceTable });
result.ToList().ForEach(row => Console.WriteLine($"{row.RowNum}, {row.Id}, {row.Column}, {row.SourceTable}"));
output:
1, 1, val1, table1
2, 2, val2, table1
3, 1, val3, table2
4, 2, val4, table2
5, 1, val5, table3
6, 2, val6, table3
Same as what you did try Distinct at the end. query syntax would be :
var List = (from t1 in dbContext.table1
join t2 in dbContext.table2 on t1.ID equals t2.ID
join t3 in dbContext.table3 on t1.ID equals t3.ID
select new
{
//t1.DesiredColumnName,
//t2.DesiredColumnName,
//t3.DesiredColumnName,
//so on
}).Distinct().ToList();

How to concat a column value based on id

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);
}

Categories