我有一张记录活动的表格。所有活动都有活动日期。我想计算给定时间段(日,月,qtr等)的活动数量。我想包括所有日期,即使是没有活动的日期。我可以在Data Tier中使用DateDimension表执行此操作,其中日期表有一个名为day的列,每个日历日包含一行,外部联接按查询分组:
DateDimension表
|日|
| 2013年1月1日00:00:00 |
| 2013年1月1日00:00:00 |
| 2013年1月1日00:00:00 |
查询
SELECT CAST(Day AS DATE), COUNT() AS CountOfActivities
FROM DateDimension dd LEFT OUTER JOIN Activities a
ON CAST(dd.Day AS DATE) = CAST(a.ActivityDate AS DATE)
WHERE Day BETWEEN MyStartDate AND MyEndDate
GROUP BY CAST(Day AS DATE)
ORDER BY CAST(Day AS DATE)
我正在使用EntityFramework,所以我想使用Linq执行此查询。 DateDimension表没有驻留在数据库中的业务值。它的存在只是为了通过提供日期列表来支持这些聚合查询,因此如果给定日期没有活动,我可以确保返回一行。
我认为我可以在内存中制作一个天数列表,并在运行时将它们编织成更简单的数据库查询的结果。通过连接来自2个IEnumerables的结果 - 1来自内存中的可触及日期和另一个来自数据库结果。我怎么能这样做?我应该这样做吗?
答案 0 :(得分:1)
这样的事情怎么样:
日期范围示例:
var from = DateTime.Today.AddDays(-30);
var to = DateTime.Today;
每天举行活动记录的词典:
var activityCounts = new Dictionary<DateTime, int>();
种子在范围内每天计数为零(这相当于设置日期维度表):
Enumerable.Range(0, (to - from).Days + 1)
.ToList()
.ForEach(x => activityCounts[from.AddDays(x)] = 0);
在范围内添加每天的实际活动计数:
context.Activities.Where(a => a.DateTime >= from && a.DateTime <= to)
.GroupBy(a => a.DateTime)
.ToList()
.ForEach(x => activityCounts[x.Key] = x.Count());
通过这种方式,您只需访问数据库以进行活动日期的活动聚合。然后,在应用程序服务器上执行结果集的填充以及日期范围内的连续日期。
只需要注意日期是如何存储在数据库中的。此代码示例期望能够根据对DateTime.Today的调用格式匹配活动字典中的键。您需要相应地在数据库查询中设置日期。