如何使用LINQ to Entities获取每组最新日期的记录
问题:使用LINQ to Entities(EF6)获取每组Market-Commodity-Currency的最新PriceValue记录
你需要从包含ID | MarketID | CommodityID | CurrencyID | PriceValue | Year | Month字段的表中,用LINQ to Entities(EF6)获取每个Market-Commodity-Currency组合的最新PriceValue记录,对吧?你的数据和预期结果我都清楚了,咱们来一步步解决。
表结构与原始数据
ID | MarketID | CommodityID | CurrencyID | PriceValue | Year | Month ---|----------|-------------|------------|------------|------|----- 1 | 100 | 30 | 15 | 3.465 | 2018 | 03 2 | 100 | 30 | 15 | 2.372 | 2018 | 04 3 | 100 | 32 | 15 | 1.431 | 2018 | 02 4 | 100 | 32 | 15 | 1.855 | 2018 | 03 5 | 100 | 32 | 15 | 2.065 | 2018 | 04 6 | 101 | 30 | 15 | 7.732 | 2018 | 03 7 | 101 | 30 | 15 | 8.978 | 2018 | 04 8 | 101 | 32 | 15 | 4.601 | 2018 | 02 9 | 101 | 32 | 18 | 0.138 | 2017 | 12 10 | 101 | 32 | 18 | 0.165 | 2018 | 03 11 | 101 | 32 | 18 | 0.202 | 2018 | 04
预期结果
ID | MarketID | CommodityID | CurrencyID | PriceValue | Year | Month ---|----------|-------------|------------|------------|------|----- 2 | 100 | 30 | 15 | 2.372 | 2018 | 04 5 | 100 | 32 | 15 | 2.065 | 2018 | 04 7 | 101 | 30 | 15 | 8.978 | 2018 | 04 8 | 101 | 32 | 15 | 4.601 | 2018 | 02 11 | 101 | 32 | 18 | 0.202 | 2018 | 04
你之前尝试的问题分析
- 第一个查询按
ID分组,这完全不对:ID是唯一主键,每个分组只会有一条记录,根本达不到按Market-Commodity-Currency组合分组的目的。 - 第二个查询分组的Key是正确的,但只获取了每组的最大日期,没有关联回原表拿到对应的
PriceValue和其他字段,所以丢失了关键数据。
解决方案:单个LINQ查询实现需求
有两种常用的方式可以实现,都能在单个查询里完成:
方式1:分组后取每组最新记录(简洁直观)
先按目标组合分组,然后在每个组内按日期(Year*100 + Month)降序排序,取第一条就是最新的完整记录:
var lastValues = from a in Analysis group a by new { a.MarketID, a.CommodityID, a.CurrencyID } into g select g.OrderByDescending(t => (t.Year * 100) + t.Month).FirstOrDefault();
方式2:子查询关联(适合复杂场景)
先通过子查询获取每个组合的最大日期,再和原表关联,筛选出对应日期的记录:
var lastValues = from a in Analysis join md in ( from item in Analysis group item by new { item.MarketID, item.CommodityID, item.CurrencyID } into g select new { g.Key.MarketID, g.Key.CommodityID, g.Key.CurrencyID, MaxDate = g.Max(t => (t.Year * 100) + t.Month) } ) on new { a.MarketID, a.CommodityID, a.CurrencyID, Date = (a.Year * 100) + a.Month } equals new { md.MarketID, md.CommodityID, md.CurrencyID, Date = md.MaxDate } select a;
说明
- 两种方式都能被EF6正确转换为SQL查询,返回包含所有字段的最新记录。
(Year*100 + Month)的计算逻辑是对的:它把年份和月份转换成一个可比较的整数(比如201804),能准确判断日期先后。
内容的提问来源于stack exchange,提问作者Giox
相关产品推荐
相关产品推荐

