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;
Related
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();
I have this SQL query that I need to translate to LINQ.
SELECT p.productId, p.name, COUNT(np.ID) AS 'salesLast70', p.quantity
FROM Products p
LEFT JOIN NOrderProducts np
ON np.product_id = p.productId
WHERE np.date_picked > DATEADD(DAY, -70, getdate())
GROUP BY p.productId, p.name, p.quantity
HAVING COUNT(np.ID) < p.quantity
Right now I have the following LINQ query.
var date70 = DateTime.Now.AddDays(-70).Date;
var almostOutOfStockProducts = from p in db.Products
join np in db.NOrderProducts on p.productId equals np.product_id
where np.date_picked > date70
group np by np.ID into npGrp
where npGrp.Count() < p.quantity
select p;
But p cannot be resolved at the end of the LINQ query at > p.quantity and select p.
I'm sure I am missing something in my LINQ query but I cannot seem to find exactly how to fix it.
EDIT:
I ended up using db.Database.SqlQuery(); with the raw query.
To achieve what you want you have to lift the quantity, name from the product up into the group by. You are doing this in your sql version with the clause GROUP BY p.productId, p.name, p.quantity but you are not doing this in your linq version.
An example would be to do:
var almostOutOfStockProducts = db.Products.Join(db.NOrderProducts, p => p.productId, np => np.product_id, (p, np) => new { p, np })
.Where(x => x.np.date_picked > date70)
.GroupBy(x => new { Quantity = x.p.quantity, Name = x.p.name, ProductId = x.p.productId})
.Where(x => x.Count() < x.Key.Quantity)
.Select(x => new {ProductId = x.Key.ProductId, Quantity = x.Key.Quantity, Name = x.Key.Name});
In the GroupBy I am bringing through the product id, quantity and name from the product into an anonymous type. This then becomes the key so I can use it in the Where clause and also in the Select at the end.
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.
So I'm trying to do a linq statement to group two db tables and select the top 25 based on how many reviews each category has. So my sql statement is
SELECT TOP 25 BusinessCategories.Category, COUNT(*) as count
FROM Reviews
JOIN BusinessCategories
ON BusinessCategories.BusinessID=Reviews.BusinessID
GROUP BY BusinessCategories.Category
ORDER BY count desc
Which works perfectly. So now to try to do this in my web api I'm having troubles. This is what I have:
var top = (from review in Db.Reviews
from category in Db.BusinessCategories
where review.BusinessID == category.BusinessID
group review by category into reviewgroups
select new TopBusinessCategory
{
BusinessCategory = reviewgroups.Key,
Count = reviewgroups.Count()
}
).OrderByDescending(x => x.Count).Distinct().Take(25);
This gives me some of the same results, but it looks like when I call the api in the browser all the counts are the same...so I'm doing something wrong.
Try this may be it works for you
var top = (from review in Db.Reviews
join category in Db.BusinessCategories
on review.BusinessID equals category.BusinessID
group review by category into reviewgroups
select new TopBusinessCategory
{
BusinessCategory = reviewgroups.Key,
Count = reviewgroups.Key.categoryId.Count() //CategoryId should be any
//property of Category or you
//can use any property of category
}).OrderByDescending(x => x.Count).Distinct().Take(25);
Solve the problem by using this
[HttpGet]
[Queryable()]
public IQueryable<TopBusinessCategory> GetTopBusinessCategories()
{
var top = (from p in Db.BusinessCategories
join c in Db.Reviews on p.BusinessID equals c.BusinessID into j1
from j2 in j1.DefaultIfEmpty()
group j2 by p.Category into grouped
select new TopBusinessCategory
{
BusinessCategory = grouped.Key,
Count = grouped.Count(t => t.BusinessID != null)
}).OrderByDescending(x => x.Count).Take(25);
return top.AsQueryable();
}
I want to write a Linq query that will return, columns with CompanyName of Supplier and number of all products of this company. Can you help me?
So far I got this:
var company = from pro in db.Products
join sup in db.Suppliers
on pro.SupplierID equals sup.SupplierID
group pro by pro.SupplierID
into g
select new { Name = g.Key, COUNT = g.Count() };
But this returns SupplierID not CompanyName. Database is Northwnd.
Use group join (i.e. join...into) to join suppliers with products and get all products of supplier in group:
from s in db.Suppliers
join p in db.Products
on s.SupplierID equals p.SupplierID into g
select new {
s.CompanyName,
ProductsCount = g.Count()
}
The following compiles and runs with Linq-for-objects. I can't vouch for whether Linq-to-SQL will cope.
var company = from sup in db.Suppliers
select new
{
Name = sup.CompanyName,
COUNT = db.Products
.Where(pro => pro.SupplierID == sup.SupplierID)
.Count()
};