【问题标题】:Linq: Count Groups of Rows Including 0 For Missing RowsLinq:计数行组,包括缺失行的 0
【发布时间】:2011-10-07 17:02:00
【问题描述】:

我想使用 Linq to Entities 将活动列表汇总为上周按天出现的次数。例如,假设我的数据库中有这样的数据:

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 包含缺失的零吗?一旦我将结果存储在内存中,我总是可以枚举结果,但是直接从数据库中获取它会很好。

【问题讨论】:

  • 直接从数据库中获取?它首先不在数据库中,因为您正在生成缺失的日期。仅使用 for 循环 IMO 可能会更容易、更有效。

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


【解决方案1】:

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

除非您的数据集非常非常大,否则与数据库请求所需的时间相比,这种内存查询和列表调整将是微不足道的。

【讨论】:

    【解决方案2】:

    您可以在给定起始值并知道要返回的天数的情况下生成日期数组。我在这里对其进行了硬编码,但您可以使用 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();
    

    【讨论】:

      【解决方案3】:

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

      在您的场景中,我将创建一个日历表并在该表上进行外部联接以获取有 0 个活动的日期。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-25
        • 1970-01-01
        • 2019-01-06
        • 2020-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多