Summary row with LINQ - c#

I have table like this:
title row1 row2
'p1' 3 4
'p2' 23 43
'p3' 21 23
and I want to have additional summary row in this table:
title row1 row2
'p1' 3 4
'p2' 23 43
'p3' 21 23
'total' 47 70
how to do that in simple way with LINQ? I have many columns so query like that:
Row r = new Row();
r.row1 = list.Sum(x=>x.row1);
r.row2 = list.Sum(x=>x.row2);
is not good idea (in my opinion)...

You can combine it into a single LINQ query like this:
var result = row
.Select(r => r)
.Union(new Row[]
{
new Row
{
Title = "total",
Row1 = row.Sum(r => r.Row1),
Row2 = row.Sum(r => r.Row2)
},
});
But ultimately you are still individually summing the rows. I can't think of a way around that.

I can't see an obvious way of improving on what you're suggesting
var total = new List<Row>{new Row{
title="total",
row1=rows.Sum(r1=>r1.row1),
row2=rows.Sum(r2=>r2.row2)
}};
var q = rows.Concat(total);

Related

LINQ extract dataTable information

I have a DataTable with these 2 columns of intereset:
Category Sum
cat1 10
cat1 15
cat2 20
cat2 25
cat3 30
cat3 35
I want to find with LINQ each first row that has a different category than “cat1” and extract the category name and sum.
So to have as output “cat2”-20 and “cat3”-30. This output can be of any kind, dictionary,dataTable,etc.
This could be split into LINQ queries, 1 to find all the different categories and 1 to find the sum.
Can you help ?
Using LINQ (Main DataTable to another DataTable which is your Extracted data)
DataTable extractedDT = new DataTable();
DataRow dtr;
extractedDT.Columns.Add("Category");
extractedDT.Columns.Add("Sum");
yourMainDataTableCollection.AsEnumerable()
.Where(w => w.Field<string>("Category") != "Cat1")
.ToList()
.ForEach(f =>
{
dtr = extractedDT.NewRow();
dtr["Category"] = f.ItemArray[0];
dtr["sum"] = f.ItemArray[1];
extractedDT.Rows.Add(dtr);
});
extractedDT is your collection output.

Dynamic Convert Row to Column in Linq

I want to convert Row to Column, actually I can implement a Static row to column as below, but it only works if I know the row position beforehand, so does anyone know how to dynamically convert a Row to Column in Linq?
This is the below table
ItemCode LOC001 LOC002 LOC003
AAA 10 11 12
BBB 13 31 14
CCC 15 18 0
This is the Static Code:
var table=(from x in Mst_LocationItems
group x by x.ItemCode into gr
select new
{
ItemCode=gr.Key,
LOC001 = gr.Where(x=>x.LocationID == "LOC001").Sum(x=>x.Reorder),
LOC002 = gr.Where(x=>x.LocationID == "LOC002").Sum(x=>x.Reorder),
LOC003 = gr.Where(x=>x.LocationID == "LOC003").Sum(x=>x.Reorder)
}).ToList();
table.Dump();

using distinct in DataTable.Select function

I have a data table and I want to populate two extra datatables using this datatable,here is a simple form of my table
My data table columns are
[name][family][id][propertyid][propertyEnergy]
John smith 1 12 Gas
John smith 1 13 Gas
John smith 1 14 null
John smith 1 15 Gas
Hannah smith 2 16 Gas
Hannah smith 2 17 Gas
Hannah smith 2 18 Gas
I want to use this query in datatable select distinct [name][family][id] from table
which results
John smith 1
Hannah smith 2
and again I use this query in another datatable select [id][propertyid][propertyEnergy] from table which results
1 12 Gas
1 13 Gas
1 14 null
1 15 Gas
2 16 Gas
2 17 Gas
2 18 Gas
I searched and found that I can DataTable.Select but examples that I have seen shows that I can only add Where sentense to DataTable.Select and I have no idea how to perform things like Distinct in it,
Can you please help me or give me some hints how to do it?
Thank you so much
I'd use Linq-To-DataTable instead:
var distinctNames = table.AsEnumerable()
.Select(row => new
{
Name = row.Field<string>("Name"),
Family = row.Field<string>("Family"),
ID = row.Field<int>("ID")
})
.Distinct();
var distinctProperties = table.AsEnumerable()
.Select(row => new
{
ID = row.Field<int>("ID"),
PropertyID = row.Field<int>("PropertyID"),
PropertyEnergy = row.Field<int>("PropertyEnergy")
})
.Distinct();
If you need two additional DataTables you have to create and fill them manually since the columns are different than the main-table. You can fill them in a loop from the queries above.
This should work as it is:
string[] nameColumns = { "Name", "Family", "ID" };
DataTable tblNames = table.Clone();
var removeColumns = tblNames.Columns.Cast<DataColumn>()
.Where(c => !nameColumns.Contains(c.ColumnName)).ToList();
removeColumns.ForEach(c => tblNames.Columns.Remove(c));
foreach (var x in distinctNames)
tblNames.Rows.Add(x.Name, x.Family, x.ID);
string[] propertyColumns = { "ID", "PropertyID", "PropertyEnergy" };
DataTable tblProperties = table.Clone();
removeColumns = tblProperties.Columns.Cast<DataColumn>()
.Where(c => !propertyColumns.Contains(c.ColumnName)).ToList();
removeColumns.ForEach(c => tblProperties.Columns.Remove(c));
foreach (var x in distinctProperties)
tblProperties.Rows.Add(x.ID, x.PropertyID, x.PropertyEnergy);

Linq query to sum by group

I have a data table like this:
Category Description CurrentHours CTDHours
LC1 Cat One 5 0
LC2 Cat Two 6 0
LC3 Cat Three 18 0
LC1 Cat One 0 9
LC2 Cat Two 0 15
LC4 Cat Four 0 21
That I need to Group and Sum to this:
Category Description CurrentHours CTDHours
LC1 Cat One 5 14
LC2 Cat Two 6 21
LC3 Cat Three 18 0
LC4 Cat Four 0 21
In other words I need to sum the two Hours columns grouping by the Category and Description columns.
I know that I could build a new table and loop through the existing data and sum the data into the new table but I thought there would be an easier way to do it using Linq. I've googled it for a few hours but all the examples I found didn't seem to fit what I was trying to do.
BTW, the odbc driver that creates the data table does not have the capability for sub queries, etc. or I would have just done it using SQL.
Use anonymous object to group by category and description. Here is Linq to DataSet query which returns grouped hours:
from r in table.AsEnumerable()
group r by new {
Category = r.Field<string>("Category"),
Description = r.Field<string>("Description")
} into g
select new {
Category = g.Key.Category,
Description = g.Key.Description,
CurrentHours = g.Sum(x => x.Field<int>("CurrentHours"),
CTDHours = g.Sum(x => x.Field<int>("CurrentHours") + x.Field<int>("CTDHours"))
}
If you are querying database (not clear from question):
from r in context.Table
group r by new {
r.Category,
r.Description
} into g
select new {
g.Key.Category,
g.Key.Description,
CurrentHours = g.Sum(x => x.CurrentHours),
CTDHours = g.Sum(x => x.CTDHours + x.CurrentHours)
}
You need to sum CurrentHours and CTDhours, so -
select new {
...
CTDHours = g.Sum(x => x.Field<int>("CTDHours") + g.Sum(x => x.Field<int>("CurrentHours")
}

How to get records with the same specific column content from a DataTable using LINQ

I have a table with personal data which looks something like this:
Identifier Name Phone Address
.............................
1 aa 23 abc
2 bb 22 abd
2 cc 11 aaa
3 dd 44 amd
4 fa 33 agd
2 ds 14 dad
3 as 55 fgg
I want to get the records with the same identifier, using LINQ, to get something like this
Identifier Name Phone Address
.............................
2 bb 22 abd
2 cc 11 aaa
2 ds 14 dad
3 dd 44 amd
3 as 55 fgg
I could order by Identifier and copy to a new DataTable, then parse it and get the records with the same identifier, but that would be expensive i guess. Is there a shorter way ?
Thank you !
Something like the code below would filter and extract the duplicates to a new DataTable with the same schema. Code assumes Identifier is an int. Replace with the appropriate names and types, as applicable.
var extractedDuplicates = (from row in table.AsEnumerable()
group row by row.Field<int>("Identifier") into rows
where rows.Count() > 1
from row in rows
select row).CopyToDataTable();
Give it a try and see how far that gets you. If there is any chance there aren't any duplicates, you will want to split this into multiple statements, as CopyToDataTable() will throw if there are no rows to copy.
var duplicateRows = from row in table.AsEnumerable()
group row by row.Field<int>("Identifier") into rows
where rows.Count() > 1
from row in rows
select row;
DataTable extractedDuplicates;
if (duplicateRows.Any())
extractedDuplicates = duplicateRows.CopyToDataTable();
else
extractedDuplicates = table.Clone();
And, of course, if you do not need a new DataTable, omit the second portion of this code entirely and just work with duplicateRows.
select * from YourTable a where a.Identifier in
(
select aa.Identifier from YourTable aa group by aa.Identifier
having (count(aa.Identifier ) > 1)
)

Categories