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

如何使用LINQ实现双层分组:先按项目再按日期聚合数据

解决LINQ双层分组:先按项目,再按日期汇总的问题

你当前的代码逻辑是直接按项目+日期作为分组键,导致每个项目的每一天都生成了独立的GroupedBillingInfo对象,而不是把同一项目的所有日期数据归集到同一个对象的Data数组里。咱们调整一下分组顺序,先按项目分组,再在项目内部按日期汇总就能解决问题啦!

修改后的代码实现

public async Task<List<GroupedBillingInfo>> Handle(GroupedBillingListQuery request, CancellationToken cancellationToken)
{
    var billing = _context.BillingSummaries
        .Where(x => x.Project.Organization.IsDeleted == false)
        // 提前关联Project实体,避免EF的N+1查询问题
        .Include(x => x.Project)
        .AsQueryable();

    var demo = await billing.ToListAsync(cancellationToken);

    var result = demo
        // 第一层分组:按项目ID聚合所有相关账单
        .GroupBy(x => x.ProjectId)
        .Select(projectGroup => new GroupedBillingInfo
        {
            ProjectId = projectGroup.Key,
            // 同一项目的名称一致,取任意一条即可
            ProjectName = projectGroup.First().Project.Name,
            // 第二层分组:在当前项目内按日期汇总价格
            Data = projectGroup
                // 按日期的年月日分组,忽略时间部分
                .GroupBy(billingItem => new 
                { 
                    billingItem.BeginApply.Year, 
                    billingItem.BeginApply.Month, 
                    billingItem.BeginApply.Day 
                })
                .Select(dateGroup => new GroupedBillings
                {
                    // 格式化为你期望的ISO日期字符串
                    StartDate = new DateTime(dateGroup.Key.Year, dateGroup.Key.Month, dateGroup.Key.Day)
                        .ToString("yyyy-MM-ddTHH:mm:ss"),
                    // 计算当天的价格总和
                    Price = dateGroup.Sum(item => item.Price)
                })
                .ToList()
        })
        .ToList();

    return result;
}

// 你的实体类无需修改
public class GroupedBillings 
{ 
    public string StartDate { get; set; } 
    public decimal Price { get; set; } 
}

public class GroupedBillingInfo 
{ 
    public List<GroupedBillings> Data { get; set; } 
    public int ProjectId { get; set; } 
    public string ProjectName { get; set; } 
}

关键逻辑说明

  • 第一层分组:仅按ProjectId分组,确保同一个项目的所有账单记录都被聚合到同一个分组中。
  • 第二层分组:在每个项目分组内部,按账单日期的「年/月/日」进行二次分组,计算该项目当天的总费用。
  • 日期格式化:通过DateTime构造函数明确生成日期对象,再转成标准的ISO格式字符串,避免手动拼接字符串可能出现的格式不一致问题。
  • 性能优化:添加.Include(x => x.Project)提前加载关联的Project实体,避免Entity Framework在后续取Project.Name时触发多次数据库查询(N+1问题)。

这样处理后,返回的结果结构就完全符合你的预期:每个项目对应一个对象,其Data数组包含该项目所有日期的费用汇总。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:48:03