Linq:计算包含0行的行数

我想使用Linq to Entities将活动列表汇总到上周的Day发生次数。 例如,假设我的数据库中有这样的数据:

Id | Date 1 | 2011-09-30 0:00:0 2 | 2011-10-02 0:00:00 3 | 2011-10-02 0:00:00 4 | 2011-10-02 0:00:00 5 | 2011-10-04 0:00:00 6 | 2011-10-04 1:30:30 7 | 2011-10-04 0:00:00 8 | 2011-10-06 0:00:00 

我们说今天的日期是2011-10-07

我想生成以下内容:

 Date | Count 2011-10-01 | 0 2011-10-02 | 3 2011-10-03 | 0 2011-10-04 | 3 2011-10-05 | 0 2011-10-06 | 1 2011-10-07 | 0 

这是我可以用来按日期对事件进行分组的示例技术,但我错过了零。

 // Using Linq to Objects for demonstration purpose only var activities = new List(); activities.Add(new Activity { Id = 1, Date = new DateTime(2011, 9, 30)}); activities.Add(new Activity { Id = 2, Date = new DateTime(2011, 10, 2)}); activities.Add(new Activity { Id = 3, Date = new DateTime(2011, 10, 2)}); activities.Add(new Activity { Id = 4, Date = new DateTime(2011, 10, 2)}); activities.Add(new Activity { Id = 5, Date = new DateTime(2011, 10, 4)}); activities.Add(new Activity { Id = 6, Date = new DateTime(2011, 10, 4, 1, 30, 30) }); activities.Add(new Activity { Id = 7, Date = new DateTime(2011, 10, 4)}); activities.Add(new Activity { Id = 8, Date = new DateTime(2011, 10, 6)}); var data = (from a in activities group a by a.Date.Date into g where g.Key > DateTime.UtcNow.AddDays(-7) select new { Date = g.Key, Count = g.Count() }).ToList(); 

结果如下:

 Date | Count 2011-10-02 | 3 2011-10-04 | 3 2011-10-06 | 1 

任何人都知道如何使用Linq to Entities包含缺失的零? 我可以在内存中一直枚举结果,但直接从数据库中获取结果会很好。

由于数据在数据库中不可用,因此使用循环生成可能同样容易,并且通过LINQ实现数据会很复杂:

 var firstDate = data.Min(d => d.Date).AddDays(-1); var lastDate = data.Max(d => d.Date).AddDays(1); for (var date = firstDate; date <= lastDate; date = date.AddDays(1)) if (!data.Exists(d => d.Date == date)) data.Add(new { Date = date, Count = 0 }); data = data.OrderBy(d => d.Date); // do something with data 

除非您的数据集确实非常大,否则列表中的内存查询和调整将与数据库请求所花费的时间相比较。

您可以生成一个给定起始值的日期数组,并知道您想要返回的天数。 我在这里很难编码,但您可以使用Min和Max从活动列表中将其拉出来并相应地确定起始值和天数。

 var allDays = Enumerable.Range(0,7).Select (i => new DateTime(2011,9,30).AddDays(i) ); 

完成后,您可以使用子选择或联接来进行聚合:

 var data = (from d in allDays select new { Date = d, Count = activities.Count (a => a.Date.Date == d) }).ToList(); 

如果您想在一个linq查询中获得结果,则必须在数据库中执行此操作。 因此, 即使他们有0活动,您也必须拥有数据库中的所有日期。 这意味着您必须创建一个新表。

在您的方案中,我将在该表上创建一个日历表和外部联接,以获取具有0个活动的日期。