2009-11-04 3 views
0

Скажем, у меня есть классы, такие как:агрегации LINQ

public class ServiceCall 
    { 
     public int ServiceCallID {get; set;} 
     public DateTime ReportedTimestamp {get; set;} 
     public bool IsPaid {get; set;} 
     public decimal LabourNet { get; set;} 
     public decimal LabourVat {get; set;} 
    } 
    public class UsedPart 
    { 
     public int UsedPartID { get; set; } 
     public decimal NetPrice { get; set; } 
     public decimal VatAmount {get; set;} 
    } 

Я хочу, чтобы вернуть данные в течение формате:

Month #CallsReceived AmountInvoiced MoneyReceived 
Jan 2009 202    €32050.20   €29200.00 
Feb 2009 213    €35050.20   €34200.00 

Сумма в счете-фактуре является общая сумма всех (NetPrices + VatAmounts) + (LabourNet + LabourVat) net a за месяц, а полученные деньги - это всего, где IsPaid = true. У меня возникли проблемы с получением запроса linq для этого отчета. Я не знаю, где взять мою группу и когда выполнить Sum.

Запрос linq, который у меня есть на данный момент, выглядит следующим образом, но я не получаю ничего близкого к тому, что я хочу в данный момент. Кто-нибудь с какой-то личностью?

var q = from s in ServiceCalls 
join up in UsedParts on s.ServiceCallID equals up.ServiceCallID into tmp 
from nullablePart in tmp.DefaultIfEmpty() 
group s by s.ReportedTimestamp.Month 
into grp 
select new 
    { 
    Month = grp.Key, 
    CallsReceived = grp.Count(), 
    AmountInvoiced = grp.Sum(s => s.UsedParts.Sum(p => p.NetPrice)), 
    }; 
+0

Пожалуйста, сообщите нам, что вы * * получаете. Имейте в виду, что это будет совокупно по сравнению с «месяцем года», а не «месяцем определенного года» - то есть он будет собираться вместе в феврале 2009 года и феврале 2008 года. –

+0

Нет смысла показывать, что у меня есть на данный момент, так как это действительно повсюду. В основном, что я хочу сделать, это агрегировать данные из рядов деталей и группировать эти данные по году/месяцу по главной строке. Не очень сложно в sql, но не может показаться, что это правильно в linq. Он будет разбит на несколько запросов, я думаю. Любые идеи о том, как лучше подойти к нему? –

ответ

0

ОК, мне пришлось разбить это на несколько подзапросов, чтобы заставить его работать. Очень может быть лучший и эффективный способ сделать это, но на данный момент у меня есть решение linq. Не включая код для получения полученных денег, поскольку он очень похож на другой код, кроме фильтрации на IsPaid = true.

Это немного отличается в моем окружении, как я использую LLBL Gen Pro, но вы можете получить основную суть от этого кода:

// Get the number of calls by month 
var callsCount = from s in ServiceCalls group s by new DateTime(s.ReportedTimestamp.Year, s.ReportedTimestamp.Month, 1) into grp select new { ReportDate = grp.Key, Count = grp.Count()}; 
//callsCount.Dump(); 

// Get the labour on all calls by month 
var serviceCallLabour = from s in ServiceCalls 
    select new 
    { 
     ReportDate = new DateTime(s.ReportedTimestamp.Year, s.ReportedTimestamp.Month, 1), 
     IsPaid = s.IsPaid, 
     GrossLabour = s.LabourChargeNet + s.LabourChargeVat 
    } 
    into labour 
    group labour by labour.ReportDate into grp 
    select new {ReportDate = grp.Key, IsPaid = grp.Select(l => l.IsPaid).First(), GrossLabour = grp.Sum(l => l.GrossLabour) }; 
//serviceCallLabour.Dump(); 

// Get the value of parts used on all calls by month 
var serviceCallParts = from s in ServiceCalls 
    join up in UsedParts on s.ServiceCallID equals up.ServiceCallID into tmp 
    from np in tmp.DefaultIfEmpty() 
    select new 
    { 
     ReportDate = new DateTime(s.ReportedTimestamp.Year, s.ReportedTimestamp.Month, 1), 
     GrossPart = np != null ? (np.NetPrice + np.VatAmount) : 0 
    } 
    into callParts 
    group callParts by callParts.ReportDate into grp 
    select new { ReportDate = grp.Key, GrossPart = grp.Sum(p => p.GrossPart) }; 
//serviceCallParts.Dump(); 

var results = from l in serviceCallLabour 
       join p in serviceCallParts on l.ReportDate equals p.ReportDate 
       join c in callsCount on l.ReportDate equals c.ReportDate     
       select new { ReportDate = l.ReportDate, CallsReceived = c.Count, AmountInvoiced = l.GrossLabour + p.GrossPart} into callAmounts 
       group callAmounts by callAmounts.ReportDate into grp 
       select new {Month = grp.Key, CallsReceived = grp.Select(c => c.CallsReceived).First(), AmountInvoiced = grp.Sum(c => c.AmountInvoiced)}; 

results.Dump(); 
0

Я знаю, этот вопрос является древней историей сейчас, но вот мой ответ.

var byMonth = 
    from sc in ServiceCalls 
    join up in UsedParts 
     on sc.ServiceCallID equals up.ServiceCallID 
     into gups 
    let tsd = sc.ReportedTimestamp.Date 
    let month = tsd.AddDays(1 - tsd.Day) 
    group new 
    { 
     Calls = 1, 
     sc.IsPaid, 
     ChargeNet = sc.LabourNet + gups.Sum(gup => gup.NetPrice), 
     ChargeVat = sc.LabourVat + gups.Sum(gup => gup.VatAmount), 
    } by month into gscs 
    select new 
    { 
     Month = gscs.Key, 
     CallsReceived = gscs.Sum(gsc => gsc.Calls), 
     AmountInvoiced 
      = gscs.Sum(gsc => gsc.ChargeNet) 
      + gscs.Sum(gsc => gsc.ChargeVat), 
     MoneyReceived 
      = gscs.Sum(gsc => gsc.IsPaid ? gsc.ChargeNet : 0m) 
      + gscs.Sum(gsc => gsc.IsPaid ? gsc.ChargeVat : 0m), 
    }; 

Наслаждайтесь!

Смежные вопросы