Linq:计算包含0行的行数

时间:2011-10-07 17:02:00

标签: c# linq entity-framework linq-to-entities

我想使用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<Activity>();
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包含缺失的零?我可以在内存中一直枚举结果,但直接从数据库中获取结果会很好。

3 个答案:

答案 0 :(得分:2)

使用循环生成可能同样容易,因为数据已经在数据库中不可用,并且通过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

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

答案 1 :(得分:1)

您可以生成一个给定起始值的日期数组,并知道您想要返回的天数。我在这里很难编码,但您可以使用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();

答案 2 :(得分:0)

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

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