[英]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.