C# Linq Group, Count & Sum - c#

I am looking for help with a Linq query I am struggling with. I am trying to build a page that shows the current stock level of all products based on the stock that has been added and the items that have been sold. These are my tables:
Product
Id
Code
Name
Stock
Id
ProductId
Quantity
Sold
Id
ProductCode
I would like the page to show the following columns:
Stock added - sum of the quantity field of all related rows from the stock table.
Items sold - count of all related rows from the Sold table
Stock remaining = stock added - items sold.
This is my attempt at the Linq query so far:
return await (from product in _context.Products
join stock in _context.Stocks on product.Id equals stock.ProductId
join so in _context.SaleProducts on product.Code equals so.Code into sold
from subSold in sold.DefaultIfEmpty()
group new { product, stock, sold } by product into g
select new StockViewModel
{
ProductId = g.Key.Id,
ProductCode = g.Key.Code,
ProductName = g.Key.Name,
StockAdded = g.Sum(x => x.stock.Quantity),
ItemsSold = g.Select(x => x.sold).Count()
})
.ToArrayAsync();
The items sold is showing the same value for each row and it is only showing products that have had stock added.
I would like to show all products whether stock has been added or not. I would also like to show all products whether any have been sold or not

Thanks to #T N for the heads up regarding Linq subqueries, this is the query I was looking for:
var stockRecords = await (from p in _context.Products
select new StockViewModel
{
ProductId = p.Id,
ProductName = p.Name,
StockAdded = (
(from s in _context.Stocks
where s.ProductId == p.Id
select s.Quantity).Sum()
),
ItemsSold = (
(from s in _context.SaleProducts
where s.Code == p.Code
select s).Count()
)
})
.ToArrayAsync();

Related

select top products in orders table

I have two tables:
product(id, reference, name)
order(id, productId, date, quantity)
Every order has one or many products. The order table can have many lines of the same product. I need to select the 5 best seller products for today in the order table. I try this join to select the products of every order on today.
from order in orders where order.date == DateTime.Today
join product in products on product.Id equals order.productId
select new {product.name, product.quantity, product.Id};
Now I have a list of products sold on today, which can have multiple lines of the same products.
So I tried this to add the quantity of the repeated product:
for (int i = 1; i <= productList.ToArray().Count(); i++)
{
foreach (var product in productList)
{
if (productList.Contains(product))
quantite += product.Quantite;
else
quantite = product.Quantite;
I didn't find a solution how to get the top 5 articles!
Try following :
var results = (from order in orders on order.date equals DateTime.Today
join product in products on product.Id equals order.productId
select new {name = product.name, quantity = order.quantity, id = product.Id})
.GroupBy(x => x.id)
.Select(x => new { name = x.First().name, id = x.Key, totalQuantity = x.Sum(y => y.quantity)}
.OrderByDescending(x => x.totalQuantity)
.Take(5)
.ToList();
You may run this simple query as native and receive the result.
select * from
(
select p.id, p.name, sum(o.quantity) qty
from "order" as o
inner join product as p on o.productid = p.id
where o.date = current_date
group by p.id -- and p.name if p.id is not primary key
) as t
order by qty desc
limit 5;

This is my SQL query that is used to retrieve the sum of quantity where product has same id, I want to use it in LINQ

This is my SQL query that is used to retrieve the sum of quantity where
product has same id, I want to use it in LINQ.
select p.ProductId,s.TotalQuantity,p.Title from Products p
join (SELECT ProductId, SUM(Quantity) AS TotalQuantity
FROM SalePerProduct s join Invoices i on s.InvoiceId = i.InvoiceId
where i.IssueDate like '%2016%'
GROUP BY s.ProductId) s
on s.ProductId = p.ProductId;
I have Tried this LINQ query but it does not work fine, It sums up the quantity having same product id but i am unable to show product title using this, need some help.
Thank you in advance.
var sales = from sale in db.SalePerProducts
join product in db.Products
on sale.ProductId equals product.ProductId
where sale.ProductId == product.ProductId
group sale by sale.ProductId into g
select new
{
ProductId = g.Key,
Sum = g.Sum(sale => sale.Quantity),
};
Here is the answer, finally i am able to retrieve multiple products with same name and PRODUCT_ID as a single record ans also sums up the quantity, Thankyou all of you.
Please vote up if you find this useful
var sales = from sale in db.SalePerProducts
join product in db.Products
on sale.ProductId equals product.ProductId
join invoice in db.Invoices
on sale.InvoiceId equals invoice.InvoiceId
where sale.ProductId == product.ProductId &&
invoice.IssueDate.Date == date
group sale by new { sale.ProductId,product.Title } into g
select new
{
ProductId = g.Key.ProductId,
Product_Title = g.Key.Title,
Quantity_Sold = g.Sum(sale => sale.Quantity)
};
var sales = from sale in db.SalePerProducts
join product in db.Products
on sale.ProductId equals product.ProductId
group new {sale, product} by sale.ProductId into g
select new
{
ProductId = g.Key,
Title = g.FirstOrDefault().product.Title,
Sum = g.Sum(s => s.sale.Quantity),
};
I removed unnecessary where clause, you have in your version.

how to use group by in a linq query?

I have a list of products with productname, productprice & category. I want to write a linq query to group all the products according to category. I have tried the following:
var p = from s in productlist
group s by s.Category into g
select new { Category = g.Key, Products = g};
With this query, it's showing a table with two column as category & product. Category column has two categories as expected but under products column, there is no data. I would love to have all the product list separated by the category.
OK..Need a bit more help on this, now when I run the code, its just
showing a table with categories column showing two categories as
expected, but the product column not showing any data.
You need to select the products from the group:
Products = g.Select(p => p).ToList()
Have a look at following with some additional properties.
var categories = from s in productlist
group s by s.category into g
select new {
Category = g.Key,
Products = g.ToList(),
ProductCount = g.Count(),
AveragePrice = g.Average(p => p.productprice)
};

LINQ: Group by aggregate but still get information from the most recent row?

Let's say I have a table that holds shipping history. I'd like to write a query that counts the amount of shipments per user and gets the shipping name from the most recent entry in the table for that user.
Table structure for simplicity:
ShipmentID
MemberID
ShippingName
ShippingDate
How do I write a LINQ C# query to do this?
It sounds like might want something like:
var query = from shipment in context.ShippingHistory
group shipment by shipment.MemberID into g
select new { Count = g.Count(),
MemberID = g.Key,
MostRecentName = g.OrderByDescending(x => x.ShipmentDate)
.First()
.ShipmentName };
Not really a LINQ answer, but personally, I'd be dropping to SQL for that, to make sure it isn't doing any N+1 etc; for example:
select s1.MemberID, COUNT(1) as [Count],
(select top 1 ShippingName from Shipping s2 where s2.MemberID = s1.MemberID
order by s2.ShippingDate desc) as [LastShippingName]
from Shipping s1
group by s1.MemberID
You can probably do LINQ something like (untested):
var qry = from row in data
group row by row.MemberId into grp
select new {
MemberId = grp.Key,
Count = grp.Count(),
LastShippingName =
grp.OrderByDescending(x => x.ShippingDate).First().ShippingName
};

How to use linq-to-sql group by to list duplicated records?

Suppose I have two tables: Category and Product. I want use linq-to-sql to select all categories (with products) that have duplicated products.
My query goes like this:
from p in db.Products
group p by p.CategoryId into c
select new
{
categoryId = c.Key,
products = from PbyC in c
group PbyC by PbyC.Name into dupl
where dupl.Count() > 1
select dupl;
}
It works but LINQPad lists empty Categories (without any duplicated Product). How to modify the query?
It would be great to have Category name display somehow instead of Id.
EDIT: I have relationship between tables.
db.Products.GroupBy(p => new { p.Name, p.CategoryId })
.Select(g => new { g.Key.CategoryId, Count = g.Count })
.Where(ng => ng.Count > 1)
.Select(ng => ng.CategoryId);
That'll select the ids of the categories with more than one Product of the same name, and is assuming you don't have any relationships set up between the objects so you'll need to join the results to the Categories table to get detailed info.
If you do have a relationship set up then you can always change the CategoryId to Category (or whatever the related object is named) and just select Category.Name in the last Select.

Categories