C# Linq到SQL C:日期之间的项
我的SQL server 2012中有两个表: 错误id、城市id、中心id、日期 检查访问id、城市id、中心id、执行日期 我正在尝试获取检查访问之间的错误数,以查看使用特定centerID的中心是否有改进,并构建图表 这是到目前为止我的代码,但我不知道如何编写where子句来获取这些检查访问之间的错误数:C# Linq到SQL C:日期之间的项,c#,linq-to-sql,C#,Linq To Sql,我的SQL server 2012中有两个表: 错误id、城市id、中心id、日期 检查访问id、城市id、中心id、执行日期 我正在尝试获取检查访问之间的错误数,以查看使用特定centerID的中心是否有改进,并构建图表 这是到目前为止我的代码,但我不知道如何编写where子句来获取这些检查访问之间的错误数: var errorsPerIV = from e in dc.Errors where e.cityID == ctid && e.c
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()
};
var IVPeriods = orderedIVs.Scan((prev, cur) => new { Begin = prev, End = cur }, cur => new { Begin = cur, End = DateTime.Now });
样本箱
比如:检查访问1和检查访问2之间有5个错误,检查访问2和检查访问3之间有2个错误,检查访问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});
}
}
我认为这在客户端是最容易处理的 首先,您希望获得感兴趣的InspectionVisitions并按日期排序,然后将其转换为可枚举项以将其拉到客户端:
var orderedIVs = InspectionVisits.Where(iv => iv.cityID == ctid && iv.centerID == centerid).Select(iv => iv.dateperformed).OrderBy(ivdp => ivdp).AsEnumerable();
现在,使用一种扩展方法,沿着可枚举项进行处理,以计算一个运行值,该方法称为扫描,因为它是按照APL Scan运算符建模的,该运算符类似于返回所有中间值的聚合:
// 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 errorsPerIV = IVPeriods.Select(ivp => new { Day = ivp.Begin.Date, Count = Errors.Where(e => ivp.Begin <= e.date && e.date <= ivp.End).Count() });
你能提供一个示例案例吗?@Sumitraj我用一个示例案例更新了我的帖子你的代码已经有了where子句-为什么你不能简单地扩展它?@AdrianWragg问题是,我想在两次检查访问之间得到错误,而不是仅仅在检查访问之后。我假设你的查询中有iv而不是mv。检查访问的日期字段是什么?
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() });