I’m trying to produce a data set for a graph that would get me the same result as the following SQL query:
select concat(year(InvoiceDate), '-', month(PaymentDate)) as Period, sum(InvoiceTable.InvoiceAmount) as BilledAmount, -sum(AccountTable.Payment) as IncomingPayments, from InvoiceTable left join AccountTable on InvoiceTable.InvoiceID = AccountTable.InvoiceID where InvoiceTable.InvoiceDate >= cast('2019/01/01' as date) and InvoiceTable.InvoiceDate < cast('2020/01/01' as date) group by concat(year(InvoiceDate), '-', month(PaymentDate))
But if I try to translate it into a linq query, I can’t get the same result, I either don’t have access to one or the other side of the junction, or I get a yearly total of one or the other side.
var data = from a in db.InvoiceTable where a.InvoiceDate >= FiscalYear.StartDate && a.InvoiceDate <= FiscalYear.EndDate join b in db.AccountTable on a.InvoiceID equals b.InvoiceID into ab from c in ab.DefaultIfEmpty() let period = string.Concat(a.InvoiceDate.Year, "-", a.InvoiceDate.Month) group a by period into g select new { Period = g.Key, Billed = g.Sum(o => o.InvoiceAmount), Collected = -b.Sum(o => (decimal?)o.Payment) ?? 0m //Can't access the right side anymore and if I group c I can't access the left side then };
I tried to nest another linq query in the Collected
column but then I would get the yearly amount on each month (g.Key
).
Advertisement
Answer
This query should work. You have to include into grouping more items. Also I have optimized your query do group by two fields, not a concatenation.
var data = from a in db.InvoiceTable where a.InvoiceDate >= FiscalYear.StartDate && a.InvoiceDate <= FiscalYear.EndDate join b in db.AccountTable on a.InvoiceID equals b.InvoiceID into ab from b in ab.DefaultIfEmpty() group new { a, b } by new { a.InvoiceDate.Year, a.InvoiceDate.Month } into g select new { Period = g.Key.Year + "-" + g.Key.Month, Billed = g.Sum(o => o.a.InvoiceAmount), Collected = -b.Sum(o => (decimal?)o.b.Payment) };