如何编写多列Group By的LINQ查询并转换指定SQL为LINQ表达式
多列Group By的LINQ实现及SQL转LINQ示例
一、多列Group By的LINQ基本写法
在LINQ中实现多列分组,核心是用匿名类型作为分组键,将需要分组的多个字段包含其中。示例如下:
方法语法
var groupedData = dbContext.YourEntities .GroupBy(item => new { item.Column1, item.Column2, // 可添加更多分组字段 }) .Select(group => new { GroupKey = group.Key, RecordCount = group.Count(), MaxValue = group.Max(item => item.NumericColumn) // 其他聚合操作 });
查询语法
var groupedData = from item in dbContext.YourEntities group item by new { item.Column1, item.Column2 } into g select new { GroupKey = g.Key, RecordCount = g.Count(), MaxValue = g.Max(x => x.NumericColumn) };
注意:匿名类型的字段名、类型必须完全匹配,才能被识别为相同的分组键。
二、目标SQL转LINQ表达式
先梳理原SQL的逻辑:
- 筛选
ContributorId = '08db4b393b1f'的记录 - 按
ContributorId、Version、格式化后的CreateTS(yyyy-MM-dd)、格式化后的UpdateTS(yyyy-MM-dd)分组 - 对每组计算
MAX(Version),并比较MAX(CreateTS)和MAX(UpdateTS)的格式化日期,取较大值作为Date - 按
Version降序排序,取第一条记录
转换后的LINQ(EF Core 3.0+ 兼容写法)
var result = dbContext.Contributions .Where(c => c.ContributorId == "08db4b393b1f") .GroupBy(c => new { c.ContributorId, c.Version, CreateDate = c.CreateTS.ToString("yyyy-MM-dd"), UpdateDate = c.UpdateTS.ToString("yyyy-MM-dd") }) .Select(g => new { g.Key.ContributorId, Version = g.Max(c => c.Version), Date = g.Max(c => c.CreateTS).ToString("yyyy-MM-dd") >= g.Max(c => c.UpdateTS).ToString("yyyy-MM-dd") ? g.Max(c => c.CreateTS).ToString("yyyy-MM-dd") : g.Max(c => c.UpdateTS).ToString("yyyy-MM-dd") }) .OrderByDescending(x => x.Version) .FirstOrDefault();
补充说明
- 若使用EF6,需将
ToString("yyyy-MM-dd")替换为DbFunctions.TruncateTime(c.CreateTS).ToString(),确保EF能正确转换为SQL的CONVERT逻辑 FirstOrDefault()对应SQL的TOP 1,若需确保返回非空结果,可使用First()(前提是确认存在匹配数据)- 分组键中的日期格式化逻辑需与SQL的
CONVERT(varchar, ...,23)完全一致,保证分组结果匹配
内容的提问来源于stack exchange,提问作者7 Reeds
相关产品推荐
相关产品推荐

