[英]Linq to SQL C#: items between dates
我的SQL Server 2012中有2个表:
Errors (id, cityID, centerID, date)
InspectionVisits (id, cityID, centerID, datePerformed)
我试图获取errors
inspection visits
之间的errors
数,以查看具有特定centerID
的中心是否有所改善并构建图表。
到目前为止,这是我的代码,但是我找不到如何编写where子句来获取这些检查访问之间的错误数量的方法:
var errorsPerIV = from e in dc.Errors
where e.cityID == ctid && e.centerID == centerid
group e by e.date.Date into g
join iv in dc.InspectionVisits on g.FirstOrDefault().cityID equals iv.cityID
where iv.centerID == g.FirstOrDefault().centerID
select new
{
Day = g.Key.Day + "/" +
g.Key.Month + "/" +
g.Key.Year,
Errors = g.Count()
};
示例案例诸如此类:在Inspection_Visit_1和Inspection_Visit_2之间出现5个错误,在Inspection_Visit_2和Inspection_Visit_3之间出现2个错误,以及在Inspection_Visit_3与今天之间出现1个错误。
编辑
如果我每天显示查询并仅在图表的x轴上标记检查访问次数,则可能会起作用。
我不确定是否有更好的方法,但是您可以执行以下操作
假设您有一个像
public class Summary
{
public DateTime? PreviousInspection;
public DateTime? NextInspection;
public int Errors;
}
那么您可以通过查询以下信息来获取大部分信息
var errorsPerIV = (from e in dc.Errors
where e.cityID == ctid && e.centreID == centreid
// Find the date of the previous inspection (if any)
let previousInspection = (from i in dc.InspectionVisits where i.cityID == e.cityID && i.centreID == e.centreID && i.datePerformed <= e.date orderby i.datePerformed descending select i.datePerformed).FirstOrDefault()
// Find the date of the next inspection (if any)
let nextInspection = (from i in dc.InspectionVisits where i.cityID == e.cityID && i.centreID == e.centreID && i.datePerformed > e.date orderby i.datePerformed ascending select i.datePerformed).FirstOrDefault()
group e by new { previousInspection , nextInspection } into results
orderby results.Key.previousInspection
select new Summary
{
PreviousInspection = results.Key.previousInspection,
NextInspection = results.Key.nextInspection ,
Errors = results.Count()
})
.ToList();
但是,如果两次访问之间没有错误,则这些访问将不会出现在您的列表中,因此您需要查找所有访问,并查看是否丢失,例如
var inspectionsDates = (from i in InspectionVisits where i.cityID == ctid && i.centreID == centreid orderby i.datePerformed select i.datePerformed).ToList();
for(int i=0; i< inspectionsDates.Count-1; i++)
{
if (!errorsPerIV.Any(a=>a.PreviousInspection == inspectionsDates[i]))
{
errorsPerIV.Add(new Summary() { PreviousInspection = inspectionsDates[i], NextInspection = inspectionsDates[i + 1], Errors = 0});
}
}
我认为这在客户端最容易处理。
首先,您要获取有趣的InspectionVisits
并按日期对其进行排序,然后转换为Enumerable
以将其拉到客户端:
var orderedIVs = InspectionVisits.Where(iv => iv.cityID == ctid && iv.centerID == centerid).Select(iv => iv.dateperformed).OrderBy(ivdp => ivdp).AsEnumerable();
现在使用沿Enumerable
处理的扩展方法以计算运行值(之所以称为Scan
,是因为它是根据APL Scan运算符建模的,就像返回所有中间值的Aggregate
一样):
// TKey combineFn(T prev, T cur)
// TKey lastKeyFn(T cur)
public static IEnumerable<TResult> Scan<T, TResult>(this IEnumerable<T> src, Func<T, T, TResult> combineFn, Func<T, TResult> lastKeyFn) {
using (var srce = src.GetEnumerator()) {
if (srce.MoveNext()) {
var prev = srce.Current;
while (srce.MoveNext()) {
yield return combineFn(prev, srce.Current);
prev = srce.Current;
}
yield return lastKeyFn(prev);
}
}
}
您可以计算检查访问的时间段:
var IVPeriods = orderedIVs.Scan((prev, cur) => new { Begin = prev, End = cur }, cur => new { Begin = cur, End = DateTime.Now });
最后,使用句点,您可以计算在每个句点之间发生的Errors
:
var errorsPerIV = IVPeriods.Select(ivp => new { Day = ivp.Begin.Date, Count = Errors.Where(e => ivp.Begin <= e.date && e.date <= ivp.End).Count() });
如果要在服务器端进行此处理,则必须将InspectionVisits
表自身连接起来,以便可以创建期间。 我尚未使用SQL Server对此进行测试:
var orderedIVs = InspectionVisits.Where(iv => iv.cityID == ctid && iv.centerID == centerid).Select(iv => iv.dateperformed).OrderBy(ivdp => ivdp);
var IVPeriods = (from ivb in orderedIVs
from ive in orderedIVs
where ivb < ive
group ive by ivb into iveg
select new { Begin = iveg.Key, End = iveg.OrderBy(iv => iv).First() })
.Concat((from ivb in orderedIVs orderby ivb descending select new { Begin = ivb, End = DateTime.Now }).Take(1));
var errorsPerIV = IVPeriods.Select(ivp => new { Day = ivp.Begin.Date, Count = Errors.Where(e => ivp.Begin <= e.date && e.date <= ivp.End).Count() });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.