linq聚集
假设我有如下课程:linq聚集,linq,aggregate,Linq,Aggregate,假设我有如下课程: public class ServiceCall { public int ServiceCallID {get; set;} public DateTime ReportedTimestamp {get; set;} public bool IsPaid {get; set;} public decimal LabourNet { get; set;} public deci
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
发票金额是一个月内所有(净价格+增值税金额)+(LabourNet+LabourVat)净额的总和,收到的金额是所有金额的总和,其中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)),
};
好的,我必须把它分解成几个子查询才能让它工作。很可能有更好、更有效的方法来实现这一点,但目前我有一个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();
我知道这是一个古老的历史问题,但这里是我的答案
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),
};
享受吧 请告诉我们你得到了什么。请记住,这将在“一年中的一个月”而不是“一年中的一个月”进行汇总-即,它将在2009年2月和2008年2月进行汇总。显示我目前拥有的东西没有多大意义,因为它确实有点到处都是。基本上,我想做的是从细节行聚合数据,并在主行上按年/月对数据进行分组。在sql中不是很难,但在linq中似乎不太可能正确。我认为,它将不得不细分为几个问题。有什么好办法吗?