我有一个在某些日期上发生的事件表,知道我要格式化数据以能够随着时间的推移绘制事件的线图。数据具有一个标签,该标签是X轴上的值和数据,该标签是y轴上的值。
数据应在两个日期之间,在此示例中,其从到处到,然后必须在天数
的时间间隔这是我的第一次尝试。
var graphData = bookings.Where(x => x.DateCreated > from && x.DateCreated < to)
.GroupBy(x => new { x.DateCreated.Year, x.DateCreated.Month, x.DateCreated.Day })
.OrderBy(x => x.Key.Year).ThenBy(x => x.Key.Month).ThenBy(x => x.Key.Day)
.Select(x => new GraphData
{
Label = x.Key.Day + "/" + x.Key.Month + "/" + x.Key.Year,
Data = x.Count()
}).ToList();
这为我提供了正确的数据,但仅在任何事件创建的日子里。
我想在图中包含任何内容的日子,以便我可以比较同一图上的不同类型的事件。
我想出了这个解决方案
var dateRanges = Enumerable.Range(0, 1 + to.Value
.Subtract(from.Value).Days)
.Select(offset => from.Value.AddDays(offset)).ToList();
var graphData = dateRanges.Select(day => new GraphData()
{
Label = day.ToString("D"),
Data = bookings.Count(x => x.DateCreated.Date == day.Date)
}).ToList();
似乎非常低效。
有什么方法可以使用linq查询来执行此操作,以便我不必在每个日期进行计数?
您的尝试的问题是,它将针对每个日期对DB进行一个查询。相反,请进行一个查询以获取具有数据的日期,然后将其与内存中的日期范围合并。
var dbData = bookings.Where(x => x.DateCreated > from && x.DateCreated < to)
.GroupBy(x => x.DateCreated.Date)
.Select(grp => new { grp.Key, grp.Count() })
.ToDictionary(x => x.Key, x => x.Count);
var graphData = Enumerable.Range(0, 1 + to.Value.Date.Subtract(from.Date.Value).Days)
.Select(offset => from.Value.Date.AddDays(offset))
.Select(day => new GraphData()
{
Label = day.ToString("D"),
Data = dbDate.TryGetValue(day, out var count) ? count : 0
}).ToList();
还确保在计算中使用Date
,因为" 1-1-2017 23:00:00"one_answers" 1-2-2-2017 00:00:00"之间的区别少于一天最终只是" 1-1-2017"。