I'm trying to generate following report from popular NorthWind
DB using Linq. It should be group by Customer
, OrderYear
.
CustomerName OrderYear Amount
I've to use the following tables Customer
, Order
and Order Details
. So far this is what I've done.
NorthwindDataContext north = new NorthwindDataContext();
var query = from o in north.Orders
group o by o.Customer.CompanyName into cg
select new
{
Company = cg.Key,
YearGroup = ( from y in cg
group y by y.OrderDate.Value.Year into yg
select new
{
Year = yg.Key,
YearOrdes = yg
}
)
};
foreach (var q in query)
{
Console.WriteLine("Customer Name : " + q.Company);
foreach (var o in q.YearGroup)
{
Console.WriteLine("Year " + o.Year);
Console.WriteLine("Sum " + o.YearOrdes.Sum(yo => yo.Order_Details.Sum( yd=> Convert.ToDecimal(yd.UnitPrice* yd.Quantity))));
}
Console.WriteLine();
}
It is giving me expected results. I compared by running t-sql
in back end.But, I've 2 questions.
foreach
, the 2nd statement generate the sum. Is it proper approach? Or there is better one available? Got it in single LINQ to SQL query:
var query = from o in north.Orders
from c in north.Customers.Where(c => c.CustomerID == o.CustomerID).DefaultIfEmpty()
from d in north.Order_Details.Where(d => d.OrderID == o.OrderID).DefaultIfEmpty()
group new { o, c, d } by new { o.OrderDate.Value.Year, c.CompanyName } into g
select new
{
Company = g.Key.CompanyName,
OrderYear = g.Key.Year,
Amount = g.Sum(e => e.d.UnitPrice * e.d.Quantity)
};
You can then simply get results:
var results = query.ToList();
Or sort it before fetching:
var results = query.OrderBy(g => g.Company).ThenByDescending(g => g.OrderYear).ToList();
I was curious about SQL that is generated by that LINQ to SQL query, so set custom Log
and here it is:
SELECT [t5].[value22] AS [Company], [t5].[value2] AS [OrderYear], [t5].[value] AS [Amount]
FROM (
SELECT SUM([t4].[value]) AS [value], [t4].[value2], [t4].[value22]
FROM (
SELECT [t3].[UnitPrice] * (CONVERT(Decimal(29,4),[t3].[Quantity])) AS [value], [t3].[value] AS [value2], [t3].[value2] AS [value22]
FROM (
SELECT DATEPART(Year, [t0].[OrderDate]) AS [value], [t1].[CompanyName] AS [value2], [t2].[UnitPrice], [t2].[Quantity]
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN [dbo].[Customers] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
LEFT OUTER JOIN [dbo].[Order Details] AS [t2] ON [t2].[OrderID] = [t0].[OrderID]
) AS [t3]
) AS [t4]
GROUP BY [t4].[value2], [t4].[value22]
) AS [t5]
ORDER BY [t5].[value22], [t5].[value2] DESC
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.6387
A bit scary, isn't it? But if you look closer, there is standard LEFT JOIN
used to combine all three tables together! All the rest is just grouping, sorting and summing.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.