How to Group more than one table By in LINQ - linq

So, I understand that group by works basically like this:
var query = from c in context.Contacts
join o in context.Orders on c.Id on o.CustomerId
group c by o.Id
select new { g.Key, g.Sum(c => c.Whatever) };
Grouping like that only allows me access to the contents of c. But what if I wanted data from both tables c and o?
var query = from c in context.Contacts
join o in context.Orders on c.Id on o.CustomerId
//insert answer here
select new { g.Key, g.Sum(c => c.Whatever), g.Sum(o => o.Whatever) };
Is that even possible?

var query = from c in context.Contacts
join o in context.Orders on c.Id equals o.CustomerId
select new
{
Contact = c,
Order = o
} into ContactAndOrder
group ContactAndOrder by ContactAndOrder.Order.Id into g
select new
{
g.Key,
ContactWhatever = g.Sum(co => co.Contact.Whatever),
OrderWhatever = g.Sum(co => co.Order.Whatever)
};

Ben's answer is a bit over-complicated, IMO. It'd be simpler to reverse the select/join pairing like this:
var query = from o in context.Orders
join c in context.Contacts on o.CustomerId equals c.Id into Customers
group o by o.Id into g
select new {
g.Key,
ContactWhatever = g.Sum(o => o.Customers.Sum(c => c.Whatever)),
OrderWhatever = g.Sum(o => o.Whatever)
};

Related

convert sql to linq with left outer join

I have a sql having left outer join, I want to convert it to linq. the sql is
Select P.Surname, P.Othername H.history
from customers P left outer join historyfiles H on H.patID = P.patId
and H.category1 = 4
where P.id = 2299
Thank you very much.
You can try this:
var query = from p in db.customers.Where(t => t.id == 2299 )
join h in db.historyfiles.Where(l => l.category1 == 4 ) on p.patID equals h.patID into gj
from h in gj.DefaultIfEmpty()
select new { p.Surname, p.Othername, h.History };

How to GroupBy data in Linq to SQL query

I've got a problem in getting my groupby's right in a Linq to SQL query.
I have 3 tables: Customers, Orders and OrderItems. The OrderItems contain the quantity and price of the items purchased.
Now I simply would like to list all the customers with the total price of all orders.
I have (amongst a number of other tries) this, but it's not compiling. There is no TotalPrice item in the Intellisense where I have the ??? in the last line.
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
//join oi in db.OrderItems on o.ID equals oi.OrderID
group c by new {c.CustomerName, TotalPrice = o.OrderItems.Sum(x => x.Quantity * x.Price)} into groupby
select groupby);
foreach (var cust in q)
Console.WriteLine("{0} {1}", cust.Min(x => x.CustomerName), cust.Sum(x => x.???);
The (easy, understandable, straight forward and simple) SQL query will look like this:
SELECT C.ID, MIN(CustomerName) CustomerName, SUM(Quantity * Price) OrderPrice
FROM Customers C
INNER JOIN ORDERS O ON C.ID = O.Customer
INNER JOIN OrderItems OI ON O.ID = OI.OrderID
GROUP BY C.ID
This works for me:
This is sums by Customer and Order
var orders = (from c in context.Customers
join o in context.Orders on c.custid equals o.custid
join od in context.OrderDetails on o.orderid equals od.orderid
select new
{
c.custid,
o.orderid,
od.qty,
od.unitprice
}).GroupBy(c => new
{
c.custid,
c.orderid
}).Select(c => new
{
c.Key.custid,
c.Key.orderid,
Summ = c.Sum(d => d.qty * d.unitprice)
}).ToList();
This is sums by Customer only
var orders = (from c in context.Customers
join o in context.Orders on c.custid equals o.custid
join od in context.OrderDetails on o.orderid equals od.orderid
select new
{
c.custid,
od.qty,
od.unitprice
}
).GroupBy(c => new
{
c.custid,
}).Select(c => new
{
c.Key.custid,
Summ = c.Sum(d => d.qty * d.unitprice)
}).ToList();
I can mess with names, but here is LinQ expression with Extension methods syntax that match your SQL:
var q = db.Customers
.GroupBy(x => new
{
x.ID,
x.CustomerName,
}, (x, group) => new
{
Id = x.ID,
CustomerName = x.CustomerName,
TotalPrice = group.Select(y => y.Orders.Sum(z => z.OrderItems.Sum(a => a.Price * a.Quantity)))
});
foreach (var cust in q)
Console.WriteLine("{0} {1}", cust.CustomerName, cust.TotalPrice);
This is also working for me:
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
join oi in db.OrderItems on o.ID equals oi.OrderID
group new {c, o.ID, oi.Quantity, oi.Price} by new {c.ID, c.CustomerName} into grp
let TotalPrice = grp.Sum(x => x.Quantity * x.Price)
select new
{
CustomerID = grp.Key.ID,
CustomerName = grp.Key.CustomerName,
TotalPrice
});
and
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
join oi in db.OrderItems on o.ID equals oi.OrderID
group new { CustomerID = c.ID, CustomerName = c.CustomerName, Price = oi.Price, Quantity = oi.Quantity} by c.ID into grp
select new
{
ID = grp.Key,
CustomerName = grp.Min(x => x.CustomerName),
TotalPrice = grp.Sum(x => x.Price * x.Quantity)
});

Linq left outer join and group by issue

Hi All my following query returns results like this:
lstView.DataSource = (from h in context.HolidayMains
join hd in context.HolidayDetails on h.Id equals hd.HolidayMainId into hd2
from hd in hd2.DefaultIfEmpty()
join e in context.Employees on h.CreatedBy equals e.Id into e2
from e in e2.DefaultIfEmpty()
join o in context.OfficeLocations on hd.OfficeLocation equals o.Id into o2
from o in o2.DefaultIfEmpty()
select new
{
h.HolidayTitle,
h.Date,
OfficeLocation = o.Name,
CreatedBy = e.Name,
h.Id
}).ToList();
But I need result like this :
How it can be done?

multiple tables join by Linq

I have 3 tables which named Player, PlayerDetails and Team. I want to write a linq statement such as
from p in Player join d in PlayerDetails on p.ID equals d.PID
and then right join team table, Player has a column named TID which face to Team table's ID.
I have tried to write a statement like
from p in Player join d in PlayerDetails on p.ID equals d.PID into PlayerGroup
from t in team join g in PlayerGroup on t.ID equals g.p.ID
It certainly can't work. I'm not sure how to write such type of query statement, table left join table2 then right join table3.
Who can help?
I believe you could do something like this:
var LeftJoin =
from p in Player
join d in PlayerDetails on p.ID equals d.PID into pd
from d in pd.DefaultIfEmpty()
select new
{
pID = p.ID,
pTID = p.TID,
dID = d.ID
};
var RightJoin =
from t in Team
join l in LeftJoin on t.ID equals l.pTID into tl
from l in tl.DefaultIfEmpty()
select new
{
tID = t.ID,
pID = l.pID,
pTID = l.PTID,
dID = l.dID
};
To do everything in one query, I think you could do (not tested) something like this:
var RightJoin =
from t in Team
join l in
(from p in Player
join d in PlayerDetails on p.ID equals d.PID into pd
from d in pd.DefaultIfEmpty()
select new
{
pID = p.ID,
pTID = p.TID,
dID = d.ID
})
on t.ID equals l.pTID into tl
from l in tl.DefaultIfEmpty()
select new
{
tID = t.ID,
pID = l.pID,
pTID = l.PTID,
dID = l.dID
};

How do I order a Group result, in Linq?

I have the following linq query, which works fine. I'm not sure how i order the group'd result.
from a in Audits
join u in Users on a.UserId equals u.UserId
group a by a.UserId into g
select new { UserId = g.Key, Score = g.Sum(x => x.Score) }
the results are currently ordered by UserId ascending. I'm after Score descending.
thanks :)
Just add the orderby clause ;-)
from a in Audits
join u in Users on a.UserId equals u.UserId
group a by a.UserId into g
let score = g.Sum(x => x.Score)
orderby score descending
select new { UserId = g.Key, Score = score };
var results =
(from a in Audits
join u in Users on a.UserId equals u.UserId
group a by a.UserId into g
select new { UserId = g.Key, Score = g.Sum(x => x.Score) })
.OrderByDescending(p=>p.Score);
Hope this will fix your problem, easier than the top one ;)
Cheers

Resources