2009-11-04 48 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), 
    }; 

享受!