Linq group by, orderbydescending, and count - c#

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

Related

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.

SQL query into LINQ in asp.net mvc

Please anyone can help me to write this sql query into Linq. i have tried..
this is my sql query
select o.OrderID,o.Nature,o.Date,od.TotalPrice,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
from [dbo].[Order] o
inner join [dbo].[tbl_OrderDetails] od on od.OrderID = o.OrderID
inner join [dbo].[tbl_OrderHistory] oh on oh.OrderID = o.OrderID
inner join [dbo].[tbl_Login] lo on o.UserID = lo.UserID
inner join dbo.tbl_OrderStatus os on oh.OrderStatusID= os.OrderStatusID
group by o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
and this is my try
public override orderDetailModel orderDetails(int id)
{
var results = from o in obj.Orders
join od in obj.tbl_OrderDetails on o.OrderID equals od.OrderID
join oh in obj.tbl_OrderHistory on o.OrderID equals oh.OrderID
join l in obj.tbl_Login on o.UserID equals l.UserID
join os in obj.tbl_OrderStatus on oh.OrderStatusID equals os.OrderStatusID
where (od.OrderID == id)
group o by new { o.Nature, o.OrderID } into
select new orderDetailModel
{
OrderID = o.OrderID,
OrderStatus = os.OrderStatus,
Date = o.Date,
DeliveryNature = o.Nature,
EmailAddress = l.EmailAddress,
FirstName = l.FirstName,
PhoneNumber = l.PhoneNumber,
TotalPrice = od.TotalPrice
};
//group o by new {o.OrderID};
orderDetailModel data = (orderDetailModel)results.FirstOrDefault();
return data;
}
but this is wrong query its not working fine please help me
You need to correct the group by clause, like you have in the SQL query like this:-
group new { o, l } by new { o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,
l.FirstName, l.EmailAddress,l.PhoneNumber } into g
select new orderDetailModel
{
OrderID = g.Key.OrderID,
OrderStatus = g.Key.OrderStatus,
Date = g.Key.Date,
..and so on
};
Since you need the grouping on two tables Order & tbl_Login you will have to first project them as anonymous type group new { o, l } then specify all the groupings and finally while projecting use Key to get the respective items.
I guess that actually, also the SQL query is not correct.
I would simply use a SELECT DISTINCT ... instead of Grouping all the columns.
Anyway, first thing to do:
Check if databases is designed correctly. As far as i can see, if you're joining the table with their Ids, i don't understand why you need to group all the data. If you have duplicates, maybe the error is in the Database design.
If you can't change your Database, or you are happy with it, then use the following LINQ approach:
var distinctKeys = allOrderDetails.Select(o => new { o.OrderID, o.Nature, o.TotalPrice, o.Date,o.OrderStatus,o.FirstName, o.EmailAddress,o.PhoneNumber }).Distinct();
var joined = from e in allOrderDetails
join d in distinctKeys
on new { o.OrderID, o.Nature,o.TotalPrice, o.Date,o.OrderStatus, o.FirstName, o.EmailAddress, o.PhoneNumber } equals d select e;
joined.ToList(); // gives you the distinct/grouped list

How to select CompanyName and number of its products?

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

LINQ: combining join and group by

I have a query that combines a join and a group, but I have a problem. The query is like:
var result = from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
group p by p.SomeId into pg
select new ProductPriceMinMax {
SomeId = pg.FirstOrDefault().SomeId,
CountryCode = pg.FirstOrDefault().CountryCode,
MinPrice = pg.Min(m => m.Price),
MaxPrice = pg.Max(m => m.Price),
BaseProductName = bp.Name <------ can't use bp.
};
As you see, it joins the Products table with the BaseProducts table, and groups on an id of the Product table. But in the resulting ProductPriceMinMax, I also need a property of the BaseProducts table: bp.Name, but it doesn't know bp.
Any idea what I'm doing wrong?
Once you've done this
group p by p.SomeId into pg
you no longer have access to the range variables used in the initial from. That is, you can no longer talk about p or bp, you can only talk about pg.
Now, pg is a group and so contains more than one product. All the products in a given pg group have the same SomeId (since that's what you grouped by), but I don't know if that means they all have the same BaseProductId.
To get a base product name, you have to pick a particular product in the pg group (As you are doing with SomeId and CountryCode), and then join to BaseProducts.
var result = from p in Products
group p by p.SomeId into pg
// join *after* group
join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id
select new ProductPriceMinMax {
SomeId = pg.FirstOrDefault().SomeId,
CountryCode = pg.FirstOrDefault().CountryCode,
MinPrice = pg.Min(m => m.Price),
MaxPrice = pg.Max(m => m.Price),
BaseProductName = bp.Name // now there is a 'bp' in scope
};
That said, this looks pretty unusual and I think you should step back and consider what you are actually trying to retrieve.
We did it like this:
from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate
group new { p, bp } by new { p.SomeId } into pg
let firstproductgroup = pg.FirstOrDefault()
let product = firstproductgroup.p
let baseproduct = firstproductgroup.bp
let minprice = pg.Min(m => m.p.Price)
let maxprice = pg.Max(m => m.p.Price)
select new ProductPriceMinMax
{
SomeId = product.SomeId,
BaseProductName = baseproduct.Name,
CountryCode = product.CountryCode,
MinPrice = minprice,
MaxPrice = maxprice
};
EDIT: we used the version of AakashM, because it has better performance
I met the same problem as you.
I push two tables result into t1 object and group t1.
from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
select new {
p,
bp
} into t1
group t1 by t1.p.SomeId into g
select new ProductPriceMinMax {
SomeId = g.FirstOrDefault().p.SomeId,
CountryCode = g.FirstOrDefault().p.CountryCode,
MinPrice = g.Min(m => m.bp.Price),
MaxPrice = g.Max(m => m.bp.Price),
BaseProductName = g.FirstOrDefault().bp.Name
};

LINQ aggregate across more than one table

I want to replicate this query in LINQ to SQL but am too unfamiliar with how to do it.
SELECT A.Recruiter, SUM(O.SaleAmount * I.Commission) --This sum from fields in two different tables is what I don't know how to replicate
FROM Orders AS O
INNER JOIN Affiliate A ON O.AffiliateID = A.AffiliateID
INNER JOIN Items AS I ON O.ItemID = I.ItemID
GROUP BY A.Recruiter
I've got this far:
from order in ctx.Orders
join item in ctx.Items on order.ItemI == item.ItemID
join affiliate in ctx.Affiliates on order.AffiliateID == affiliate.AffiliateID
group order //can I only group one table here?
by affiliate.Recruiter into mygroup
select new { Recruiter = mygroup.Key, Commission = mygroup.Sum(record => record.SaleAmount * ?????) };
group new {order, item} by affiliate.Recruiter into mygroup
select new {
Recruiter = mygroup.Key,
Commission = mygroup
.Sum(x => x.order.SaleAmount * x.item.Commission)
};
And an alternative way of writing the query:
from aff in ctx.Affiliates
where aff.orders.Any(order => order.Items.Any())
select new {
Recruiter = aff.Recruiter,
Commission = (
from order in aff.orders
from item in order.Items
select item.Commission * order.SaleAmount
).Sum()
};
try linqpad, just Google, amazing tool!

Categories