每小时/每日/每周汇总读数数据,并在缺失的时间间隔内扩展最后已知值

时间:2014-05-13 13:16:46

标签: c# sql wpf linq-to-entities

我有一份检查表,其中有读数

Inspections
     |_ Readings : DateTaken, Status(0:OK, 1:WARNING, 2:CRITICAL)

示例数据:

Date Interval    1    2    3    4    5    6    7    8    9    10
-------------------------------------------------------------------
Inspection #1    0    -    -    1    2    2    0    -    -    -                    
Inspection #2    2    -    -    1    0    1    -    -    -    0            
Inspection #3    0    0    0    0    0    0    0    0    0    0                   
-------------------------------------------------------------------
Worst Status     2    2    2    1    2    2    1    1    1    0    

在图表上,我需要显示一段时间内的整体最差状态(按小时/天/周分组) 请记住,在一次阅读中CRITICAL的检查将继续为CRITICAL,直到读数表明它现在为OK,但两者之间可能没有任何读数。

目前,我为每个检查的每个日期间隔生成一个字典,用于所需的时间刻度,使每个间隔的最后已知状态转发,并将它们存储在列表中:

// get readings for every point
foreach (Inspection insp in list)
{                    
    Dictionary<DateTime, int> dict = new Dictionary<DateTime, int>();

    DateTime startDate = GetStartDateFromUserSelection();                    
    var readings = insp.Readings.Where(a => a.DateTaken >= startDate).GroupBy(a => a.DateTaken.Date);

    // status to bring the previous date interval's value
    int status = 0;
    // loop, increment from start date to now daily (TODO: hourly/weekly)
    for (DateTime date = startDate; date <= DateTime.Today; date = date.AddDays(1))
    {
        // group all readings for inspection by date interval
        var dailyReadings = readings.Where(a => a.Key.Date == date.Date).FirstOrDefault();
        if (dailyReadings != null)
        {
            Reading reading = dailyReadings.OrderByDescending(a => a.Status).FirstOrDefault();
            if (reading != null)
                status = read.Status;
        }
        // status will continue to stay as last-set value until a reading resets it
        dict.Add(date, status);
    }
statusList.Add(dict);
}

然后我遍历所有列表以找到特定日期间隔的最高读数:

for (int i = 0; i < statusList[0].Count; i++)
{
    DateTime date = statusList[0].ElementAt(i).Key;
    int status = 0;
    foreach (var list in statusList)
    {
        if (list.Count > 0)
        status = list.ElementAt(i).Value > status ? list.ElementAt(i).Value : status;
    }
    worstStatus.Add(date, status);
}
chart.DataContext = worstStatus;

我知道这不是最好的方法,但我的逻辑大脑是AWOL,我需要一些帮助!如果没有这么多处理,我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:0)

希望是一个更简洁的版本(虽然我并没有声称它在实际处理方面要快得多):

var dates = Enumerable.Range(0, (DateTime.Now - startDate).Days + 1)
                      .Reverse()
                      .Select(i => DateTime.Now.Date.AddDays(-i))
                      .ToArray();

var dailyReadings =
   list.SelectMany(inspection => dates.Select(d => 
      new
      {
         Date = d,
         Reading = inspection.Readings
                             .OrderBy(r => r.DateTaken)
                             .LastOrDefault(reading => reading.DateTaken <= d) 
      }));

var worstCases =
   dailyReadings.GroupBy(dr => dr.Date)
                .Select(g => new
                             {
                                Date = g.Key,
                                Status = g.Max(i => i.Reading == null
                                                     ? Status.Ok
                                                     : i.Reading.Status)
                             });