2009-11-04 50 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查詢。我不確定在哪裏分組以及何時執行總和。

我現在有的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年2月和2008年2月結合在一起。 – 2009-11-04 14:29:00

+0

顯示我目前擁有的內容沒有太多意義這真的有點兒太過分了。 基本上我想要做的是彙總來自詳細信息行的數據,並將這些數據按主/從行的年/月進行分組。在sql中不是非常困難,但似乎無法在linq中正確使用它。 它將不得不分解成我認爲的幾個查詢。任何想法的最佳方法來處理它? – 2009-11-04 15:45:08

回答

0

好吧,我不得不把它分解成幾個子查詢才能正常工作。這樣做可能會有更好更有效的方式,但我現在有一個linq解決方案。不包括獲得收到貨幣的代碼,因爲它與其他代碼非常相似,只是在IsPaid = true上進行過濾。

這是在我的環境略有不同,因爲我使用LLBL根臨,但你可以從這個代碼得到基本要點:

// 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), 
    }; 

享受!