如何用LINQ实现可变列名、列数的动态Pivot,生成跨年月销售对比报表
问题原因
你当前的分组逻辑是按「年份+月份+商品名称」聚合,得到的每一行对应单个商品某一年某一个月的销售额,是纵向排布的结构,自然无法实现同月份不同年份销售额的横向并列展示。
解决方法
你需要做两次分组:第一次先聚合出单商品、单年、单月的总销售额,第二次以「商品名称+月份」为维度做分组,将同组内不同年份的销售额提取为独立字段即可。
示例代码
// 第一步:先聚合出单商品+年+月维度的总销售额,加载到内存做后续透视处理 var monthlyBase = (from s in legacyContext.For<Sales>().Query join p in legacyContext.For<Product>().Query on s.ProductId equals p.ProductId group s by new { p.ProductName, Year = s.CreationUtcTime.Year, Month = s.CreationUtcTime.Month } into g select new { g.Key.ProductName, g.Key.Year, g.Key.Month, Total = g.Sum(x => x.TotalSales) }).ToList(); // 第二步:按商品+月份分组,透视出不同年份的销售额 // 以对比2022、2023两年数据为例,可根据实际需求替换为动态年份参数 var reportResult = from item in monthlyBase group item by new { item.ProductName, item.Month } into pg select new { 商品名称 = pg.Key.ProductName, 月份 = pg.Key.Month + "月", 2022年销售额 = pg.FirstOrDefault(x => x.Year == 2022)?.Total ?? 0, 2023年销售额 = pg.FirstOrDefault(x => x.Year == 2023)?.Total ?? 0, 同比差额 = (pg.FirstOrDefault(x => x.Year == 2023)?.Total ?? 0) - (pg.FirstOrDefault(x => x.Year == 2022)?.Total ?? 0) };
补充说明
如果需要对比的年份不固定,可以提前取出所有涉及的年份集合,再通过循环动态生成对应列的取值逻辑即可。另外你原有代码中重复给CreatedDateMonth赋值的笔误也可以同步修正。
内容的提问来源于stack exchange,提问作者user3509547
相关产品推荐
相关产品推荐

