C# Lambda按Date与UserId分组行转列生成新集合的实现方法
实现方案
步骤1:定义行转列后的目标DTO类
首先定义用于接收转换结果的类,属性对应你需要的目标字段:
public class TransactionPivotResult { // 分组维度字段 public DateTime Date { get; set; } public int UserId { get; set; } // 行转列后的TypeId对应值字段,类型和原始Value保持一致,使用可空类型存储无匹配的空值 public decimal? TypeId1 { get; set; } public decimal? TypeId2 { get; set; } public decimal? TypeId3 { get; set; } public decimal? TypeId4 { get; set; } }
步骤2:对分组结果做投影转换
你已经拿到了按Transaction_Date和User_Id分组的结果,直接通过Select方法对每个分组做字段匹配即可:
var pivotResult = groupTranDate.Select(g => new TransactionPivotResult { Date = g.Key.Transaction_Date, UserId = g.Key.User_Id, // 匹配每个TypeId对应的Value,无匹配则返回空 TypeId1 = g.FirstOrDefault(x => x.TypeId == 1)?.Value, TypeId2 = g.FirstOrDefault(x => x.TypeId == 2)?.Value, TypeId3 = g.FirstOrDefault(x => x.TypeId == 3)?.Value, TypeId4 = g.FirstOrDefault(x => x.TypeId == 4)?.Value }).ToList();
优化建议:直接在EF侧完成转换(减少内存占用)
如果不需要保留原始分组数据,可以把投影逻辑直接写到EF查询链路中,不需要把全量分组数据加载到内存后再处理,性能更高:
var pivotResult = db.System_Transactions .GroupBy(g => new { g.Transaction_Date, g.User_Id }) .Select(g => new TransactionPivotResult { Date = g.Key.Transaction_Date, UserId = g.Key.User_Id, TypeId1 = g.Where(x => x.TypeId == 1).Select(x => (decimal?)x.Value).FirstOrDefault(), TypeId2 = g.Where(x => x.TypeId == 2).Select(x => (decimal?)x.Value).FirstOrDefault(), TypeId3 = g.Where(x => x.TypeId == 3).Select(x => (decimal?)x.Value).FirstOrDefault(), TypeId4 = g.Where(x => x.TypeId == 4).Select(x => (decimal?)x.Value).FirstOrDefault() }).ToList();
注意:如果同一个
Date+UserId下存在同一个TypeId的多条数据,可以根据业务需求将FirstOrDefault替换为Sum、Average等聚合函数实现对应逻辑。
内容的提问来源于stack exchange,提问作者นพรัตน์ ทองเนื่อแปด
相关产品推荐
相关产品推荐

