You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何按日期(天)对数据库记录进行GroupBy分组?

按日期分组数据库记录的正确实现方式

问题分析

  1. 第一次尝试的问题:

    • 仅按Day分组会把不同年月的同一天归为一组(比如2022/5/22和2023/5/22会被分到同一组),完全不符合你的需求。
    • 部分EF Core版本对直接访问DateTime.Day的翻译支持有限,直接导致"LINQ表达式无法翻译"的错误。
  2. 第二次尝试的问题:

    • 你的查询逻辑是从每个分组里仅取第一条记录的属性,这和你要的「每个日期对应一组记录列表」的需求完全不符。
    • 多次调用FirstOrDefault()会生成低效的SQL查询,数据量稍大就会导致数据库响应缓慢,最终让API一直处于pending状态。

正确实现方案

方案1:按日期分组并保留完整记录列表

如果需要保留每个日期下的所有原始记录,直接按日期部分(忽略时间)分组后取出整组数据:

var groupedRegistrations = await ctx.Registration
    .GroupBy(r => r.DateReference.Date) // 按完整日期(年-月-日)分组,忽略时间部分
    .Select(g => new 
    {
        Date = g.Key,
        Registrations = g.ToList() // 获取该日期下的所有记录
    })
    .OrderBy(result => result.Date)
    .ToListAsync();

执行后会得到一个集合,每个元素包含日期和该日期对应的所有Registration记录。

方案2:映射到ViewModel并保留每组记录

如果需要将每组记录转换为RegistrationViewModel列表,直接在分组内做投影转换:

var groupedViewModels = await ctx.Registration
    .GroupBy(r => r.DateReference.Date)
    .Select(g => new 
    {
        Date = g.Key,
        RegistrationList = g.Select(r => new RegistrationViewModel
        {
            RegistrationId = r.RegistrationId,
            PeopleId = r.PeopleId,
            DateReference = r.DateReference,
            DateChange = r.DateChange,
            UserRef = r.UserRef,
            CommissionId = r.CommissionId,
            ActivityId = r.ActivityId,
            MinuteWorked = r.MinuteWorked
        }).ToList()
    })
    .OrderBy(result => result.Date)
    .ToListAsync();

方案3:聚合日期维度的统计数据(可选)

如果你的需求是获取日期维度的聚合数据(比如每天总工作时长),可以用聚合函数实现:

var dailyAggregates = await ctx.Registration
    .GroupBy(r => r.DateReference.Date)
    .Select(g => new 
    {
        Date = g.Key,
        TotalMinutes = g.Sum(r => r.MinuteWorked),
        DailyRecordCount = g.Count()
    })
    .OrderBy(result => result.Date)
    .ToListAsync();

关键注意事项

  • 给DateReference字段添加数据库索引,否则分组查询会随着数据量增大变得异常缓慢,直接导致API pending。
  • 避免在分组后多次调用FirstOrDefault(),这种写法会生成冗余的SQL查询,效率极低。
  • 若使用旧版本EF Core或特定数据库(如PostgreSQL),可能需要用EF.Functions.DateTrunc("day", r.DateReference)替代r.DateReference.Date,具体取决于数据库的日期截断函数支持。

内容的提问来源于stack exchange,提问作者devludo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 16:15:32