首页 文章

Linq - 按日期分组并选择计数

提问于
浏览
24

我目前正在解决一个问题,我想运行一个查询,按选定的日期对结果进行分组 .

对于这个例子,想象一个像这样的简单模型:

public class User
{
      public DateTime LastLogIn {get; set;}
      public string Name {get; set;}
}

我正在寻找的解决方案是获取按日期登录的用户数 . 在数据库中,DateTime与日期和时间组件一起存储,但对于此查询,我真的只关心日期 .

我现在拥有的是:

context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)EntityFunctions.TruncateTime(x.Key)
            }).ToList();

然而,上面返回一个空列表 .

最终目标是拥有一个对象列表,其中包含一个值(一天登录的用户数)和一天(相关日期)

有什么想法吗?

将查询更改为:

context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)x.Key
            }).ToList();

它现在返回一个包含单个项目的列表,其中Value是与where子句匹配的Users总数,而Day是第一天 . 它似乎仍然没有能够分组

NOTE: 原来上面的代码是对的,我只是做了别的错事 .

它正在生成的Sql(注意这里可能是非常轻微的语法错误,我为此调整了它):

SELECT 
1 AS [C1], 
[GroupBy1].[A1] AS [C2], 
 CAST( [GroupBy1].[K1] AS datetime2) AS [C3]
FROM ( SELECT 
        [Filter1].[K1] AS [K1], 
        COUNT([Filter1].[A1]) AS [A1]
        FROM ( SELECT 
                 convert (datetime2, convert(varchar(255), [Extent1].[LastLogIn], 102) ,  102) AS [K1], 
                1 AS [A1]
                FROM [dbo].[Users] AS [Extent1]
                WHERE (([Extent1].[LastLogIn] >= @p__linq__1) AND ([Extent1].[LastLogIn] <= @p__linq__2)
        )  AS [Filter1]
       GROUP BY [K1]
)  AS [GroupBy1]

4 回答

  • 25

    你不需要第二个 TruncateTime

    context.Users
        .Where((x.LastLogIn  >= lastWeek) && (x.LastLogIn <= DateTime.Now))
        .GroupBy(x => DbFunctions.TruncateTime(x.LastLogIn))
        .Select(x => new
        {
            Value = x.Count(),
            // Replace the commented line
            //Day = (DateTime)DbFunctions.TruncateTime(x.Key)
            // ...with this line
            Day = (DateTime)x.Key
        }).ToList();
    

    GroupBy 已经截断了 DateTime 的时间,因此您无需再次调用它 .

    要使用 DbFunctions.TruncateTime ,您需要引用程序集 System.Data.Entity 并包含 using System.Data.Entity;

    Note: 已编辑以解决 EntityFunctions 的弃用问题 .

  • 1

    试试这个:

    .GroupBy(x => new {Year = x.LastLogIn.Year, Month = x.LastLogIn.Month, Day = x.LastLogIn.Day)
                    .Select(x => new
                    {
                        Value = x.Count(),
                        Year = x.Key.Year,
                        Month = x.Key.Month,
                        Day = x.Key.Day
                    })
    
  • 2

    你可以轻松地做到:

    yourDateList.GroupBy(i => i.ToString("yyyyMMdd"))
                 .Select(i => new
                 {
                     Date = DateTime.ParseExact(i.Key, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None),
                     Count = i.Count()
                 });
    
  • 1

    您也可以在一行中完成 .

    var b = (from a in ctx.Candidates select a)
                .GroupBy(x => x.CreatedTimestamp.Date).Select(g => new { Date=(g.Key).ToShortDateString(), Count = g.Count() });
    

相关问题