Skip to content
Advertisement

How can I group a joined query with linq

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)
        };
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement