How to SUM the value from DISTINCT row using LINQ - c#

Datatable as below:
Item CartonID Quantity
A 0001 1000
A 0002 500
A 0003 250
A 0002 500
B 0002 500
B 0003 250
My output suppose to be this:
ItemNo CartonID TotalCarton TotalQuantity
A 0001,0002,0003 3 2250
B 0002,0003 2 750
But my result is list as below:
ItemNo CartonID TotalCarton TotalQuantity
A 0001, 0002, 0003 3 2,250
B 0002, 0003 2 750
My code is list as below:
var items = ( from item in dtTest.AsEnumerable()
group item by new
{
Item_No=item.Field<string>("Item")
}
into g
select new
{
g.Key.Item_No,
TotalCarton = (from p in dtTest.AsEnumerable()
where p.Field<string>("Item") == g.Key.Item_No
select p.Field<string>("CartonID")).Distinct().ToArray().Count(),
Total_Quantity =g.Sum((p=>p.Field<decimal>("Quantity"))).ToString("###,###,###,###"),
CartonID = (from p in dtTest.AsEnumerable()
where p.Field<string>("Item") == g.Key.Item_No
select p.Field<string>("CartonID")).Distinct().ToArray().Aggregate
((p1, p2) => p1 + ", " + p2)
}).ToList();
Anyone can tell me how to sum the total with distinct Carton ID. Thanks in advance.

You should GroupBy CartonID and then sum the groups elements:
something like this
dtTest.GroupBy(x => x.CartonId)
.ToDictionary(y => y.Key, y => y.Sum(z => z.Quantity);
This will return a dictionary containing the total quantity per each CartonID. I hope i understood correctly that this is what you want.
Based on the Output that you said is supposed to be retrieved, i adapted the query to this:
dtTest.GroupBy(x => x.ItemNo)
.Select(itemGroup => new {
itemGroup.Key,
itemGroup.Distinct(item => item.CartonID),
itemGroup.Distinct(item => item.CartonID).Count(),
itemGroup.Sum(item => item.Quantity)
});

Related

How to display product using group by prices in c# console app

I have list of products which has id, name and price. I want to show it in console using prices such as
Price 1 to 100
--list of products
price 101 to 200
--list of products
and it so on till last highest price.
I need to determine at runtime how many segments I need to create based upon highest price.
If you have a list called products that have a property called Price you could use a basic Linq expression with OrderBy and Where
Edit: now that I understand your question better, you could create a new list for each segment of 100's.
so something like this:
products = products.OrderBy(x => x.Price).ToList();
var subProducts = products.Where(x => x.Price > 0 && x.Price < 100).ToList();
// then print each item in the list here.
// then do the next segment
subProducts = products.Where(x => x.Price >= 100 && x.Price < 200).ToList();
and you could put this basic format in a loop and then iterate through by the 100's to get each segment.
There are two problems to solve here. First, you need to figure out, for any given price, how to categorize it into a price range. The information you've given in your post isn't quite specific enough unless all your prices are in whole numbers, but I'll make an educated guess here.
// Model
record ProductPriceRange(decimal Low, decimal High);
// Desired behavior
GetPriceRange(0.01m).Should().Be(new ProductPriceRange(0.01m, 100m));
GetPriceRange(100m).Should().Be(new ProductPriceRange(0.01m, 100m));
GetPriceRange(100.01m).Should().Be(new ProductPriceRange(100.01m, 200m));
// Implementation
ProductPriceRange GetPriceRange(decimal price)
{
var groupBasis = (int)(((price - 0.01m) / 100)) * 100 + 0.01m;
return new ProductPriceRange(groupBasis, groupBasis + 99.99m);
}
Then your grouping code can look something like this:
var productGroups =
from p in products
group p by GetPriceRange(p.Price) into g
select new {
PriceRange = g.Key,
Products = g.ToList()
};
foreach (var g in productGroups)
{
Console.WriteLine($"{g.PriceRange.Low} - {g.PriceRange.High}: {string.Join(", ", g.Products)}");
}
Sample output:
0.01 - 100.00: Product { Price = 0.01 }, Product { Price = 99.99 }, Product { Price = 100 }
100.01 - 200.00: Product { Price = 100.01 }, Product { Price = 199.99 }, Product { Price = 200 }
200.01 - 300.00: Product { Price = 200.01 }
Try the following:
var query = products
.GroupBy(p => (int)(p.Price / 100))
.OrderBy(g => g.Key)
.Select(g => new {
Lower = g.Min(x => x.Price),
Higher = g.Max(x => x.Price),
Items = g.OrderBy(x => x.Price).ToList())
})
.ToList();
It will return list of lists.

sum distinct values from a column in datagridview

I have a datagridview with two columns like this:
group | quantity
------------------------
chest | 3
legs | 7
back | 2
chest | 1
back | 5
legs | 2
What I'm trying to do is to get the sum of distinct group to a list and use that list for populate another datagridview.
So the result must be in this example:
chest | 4
legs | 9
back | 7
I've tried some linq query code but without any success.
How can I do it?
Here's some Linq queries I tried:
List<string> vv = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(x => !x.IsNewRow)
// either..
.Where(x => x.Cells[7].Value != null)
//..or or both
.Select(x => x.Cells[7].Value.ToString())
.Distinct()
.ToList();
dataGridView6.DataSource = vv;
EDIT
the group column is being auto filled after a selection of another column combobox, the quantity is filled manually. For the group by I found this code and works but throw an error if a cell is empty:
var Sums = dataGridView1.Rows.Cast<DataGridViewRow>()
.GroupBy(row => row.Cells[7].Value.ToString()) // group column
.Select(g => new { User = g.Key, Sum = g.Sum(row => Convert.ToInt32(row.Cells[1].Value)) });
dataGridView6.DataSource = Sums.ToList();
ok, here the solution that works:
var Sums = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells[7].Value != null)
.GroupBy(row => row.Cells[7].Value.ToString()) // group column
.Select(g => new { User = g.Key, Sum = g.Sum(row => Convert.ToInt32(row.Cells[1].Value)) }); // quantity column
dataGridView6.DataSource = Sums.ToList();

Linq - how to write group by query to get quantity of each product

Hello every one I have a data as follows
Item Qty Type
1 2 Purchase
1 3 Sales
1 8 Return
2 5 Purchase
2 4 Sales
2 5 Return
Now I have a requirement of getting quantity of each item by Subtracting Sales and Return with Purchase
And my final output would be
item Qty
1 -9
2 -4
Note : To get quantity: Qty => (Purchase Qty - SalesQty - Return Qty) eg: (2-3-8)
So how can I write this query on LINQ or in SQL
SQL Query:
SELECT Item, SUM(CASE Type WHEN 'Purchase' THEN Qty ELSE -Qty END) AS Qty
FROM Table
GROUP BY Item
LINQ:
Items
.GroupBy(p => p.Item)
.Select(p => new
{
Item = p.Key,
Qty = p.Sum(x => x.Type == "Purchase" ? x.Qty : -x.Qty)
});
If you are using LINQ to SQL, you can do:
var ans = from i in src
group i by i.Item into ig
let PurchaseQty = ig.Where(i => i.Type == "Purchase").Sum(i => i.Qty)
let SalesQty = ig.Where(i => i.Type == "Sales").Sum(i => i.Qty)
let ReturnQty = ig.Where(i => i.Type == "Return").Sum(i => i.Qty)
select new {
Item = ig.Key,
Qty = PurchaseQty - SalesQty - ReturnQty
};
If you are using LINQ to EF 2.2, it may work but will do the grouping client side. If you are using EF 3.x, good luck!

LINQ: Select a column based on another column value

After executing some LINQs, I have this data as IQueryable of an anonymous type:
Cat Type Count
----------------
A 1 10
B 1 15
C 1 25
D 1 5
A 2 15
C 2 30
D 2 20
B 2 10
Now, for every Cat I want to select Count based on Type values with LINQ.
Output should be like this:
Cat Type1Count Type2Count
---------------------------
A 10 15
B 15 10
C 25 30
D 5 20
You can try to use groupby then select to do pivot.
var query = myList
.GroupBy(c => c.Cat)
.Select(g => new {
Cat = g.Key,
Type1Count = g.Where(a => a.Type == 1).Sum(c => c.Count),
Type2Count = g.Where(a => a.Type == 2).Sum(c => c.Count)
});
c# online
Result
Cat:A Type1Count:10 Type2Count:15
Cat:B Type1Count:15 Type2Count:10
Cat:C Type1Count:25 Type2Count:30
Cat:D Type1Count:5 Type2Count:20
So basically you need to group by Cat and Type and get sum of Count:
myList.GroupBy(x => new { x.Cat, x.Type }).Select(x => new { Cat = x.Key.Cat, Type = x.Key.Type, CountForTypeAndCat = x.Sum(y=>y.Count) })
This will allow you go get information for any Type not only 1 and 2
foreach (var item in query.OrderBy(x=>x.Cat).ThenBy(x=>x.Type))
{
Console.WriteLine(string.Format("Cat:{0} Type:{1} CountForTypeAndCat:{2}", item.Cat, item.Type, item.CountForTypeAndCat));
}

linq, group by and count

I have a list of Unions with several members and another table with page hits by Union.
Need a report that list each union, the number of each type of member and the clicks (page views).
clicks are on a separate table with a date and unionID
this is close but doesn't really have the results I want. The count shows the total of members but not the total of clicks. How do i get the total clicks? (count records in clicks table that match the UnionID)
(from c in db.view_Members_Details
join h in db.tbl_Clicks on c.unionID equals h.unionID
group c by new { c.UnionName, h.unionID } into g
select new
{
TotalClicks = g.Count(),
UnionName = g.Key.UnionName,
userTypeID1 = g.Where(x => x.UnionName.Equals(g.Key.UnionName) && x.userTypeID.Equals(1)).Count(),
userTypeID2= g.Where(x => x.UnionName.Equals(g.Key.UnionName) && x.userTypeID.Equals(2)).Count(),
userTypeID3= g.Where(x => x.UnionName.Equals(g.Key.UnionName) && x.userTypeID.Equals(3)).Count(),
}).ToList();
results should be:
Clicks Count | Union Name | userTypeID1 Count | userTypeID2 Count | userTypeID3 Count |
I don't think you need the first condition in your WHERE, because you're already grouping on the UnionName.
g.Count(x => x.userTypeID == 3) //etc for 1, 2, 3
As for the clicks, try the following:
TotalClicks = g.Count(x => x.unionID == g.Key.unionID)

Categories

Resources