如何用SQL查询与Entity Framework获取各ProcessID的最大ID行?
如何筛选每个ProcessID对应的最大ID行(SQL与Entity Framework实现)
刚好处理过类似的需求,我来给你拆解两种实现方式,结合你的表结构来具体说明:
SQL 查询实现
方法1:窗口函数(推荐,简洁高效)
如果你的数据库支持窗口函数(比如SQL Server、MySQL 8+、PostgreSQL等),这是最直观高效的写法。用ROW_NUMBER()给每个ProcessID分组内的行按ID降序编号,取编号为1的行就是每个组里ID最大的记录:
SELECT ID, ProcessID, MESSAGE, STATUS FROM ( SELECT ID, ProcessID, MESSAGE, STATUS, ROW_NUMBER() OVER (PARTITION BY ProcessID ORDER BY ID DESC) AS RowNum FROM YourTableName -- 替换成你的实际表名 ) t WHERE t.RowNum = 1;
解释:PARTITION BY ProcessID把数据按ProcessID拆分分组,ORDER BY ID DESC让每个组里ID最大的行排在第一位,最后筛选RowNum=1就能拿到目标结果。
方法2:子查询关联(兼容老版本数据库)
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以先分组找出每个ProcessID的最大ID,再关联原表获取完整行数据:
SELECT t1.ID, t1.ProcessID, t1.MESSAGE, t1.STATUS FROM YourTableName t1 INNER JOIN ( SELECT ProcessID, MAX(ID) AS MaxID FROM YourTableName GROUP BY ProcessID ) t2 ON t1.ProcessID = t2.ProcessID AND t1.ID = t2.MaxID;
解释:子查询先得到每个ProcessID对应的最大ID值,再通过Inner Join匹配原表中ID等于这个最大值的记录,就能拿到完整的行数据。
Entity Framework 实现
假设你已经定义了对应表的实体类ProcessRecord,DbContext里的DbSet是ProcessRecords,包含ID, ProcessID, MESSAGE, STATUS这些属性。
方法1:Linq GroupBy 写法(最简洁)
通过分组后,在每个组内筛选出ID最大的实体:
var result = dbContext.ProcessRecords .GroupBy(record => record.ProcessID) .Select(group => group.OrderByDescending(r => r.ID).FirstOrDefault()) .ToList();
解释:先按ProcessID分组,每个组内按ID从大到小排序,取第一个元素就是该组ID最大的记录。
方法2:Linq Join 写法(对应SQL的关联思路)
先查询每个ProcessID的最大ID,再和原实体集合做Join匹配:
// 先获取每个ProcessID对应的最大ID var maxIdPerProcess = dbContext.ProcessRecords .GroupBy(r => r.ProcessID) .Select(g => new { ProcessID = g.Key, MaxID = g.Max(r => r.ID) }); // 关联原表获取完整记录 var result = dbContext.ProcessRecords .Join(maxIdPerProcess, record => new { record.ProcessID, record.ID }, maxId => new { maxId.ProcessID, maxId.MaxID }, (record, maxId) => record) .ToList();
方法3:执行原生SQL(适合熟悉SQL的场景)
如果更习惯写SQL,可以直接在EF里执行原生SQL语句:
var result = dbContext.ProcessRecords .FromSqlRaw(@" SELECT ID, ProcessID, MESSAGE, STATUS FROM ( SELECT ID, ProcessID, MESSAGE, STATUS, ROW_NUMBER() OVER (PARTITION BY ProcessID ORDER BY ID DESC) AS RowNum FROM YourTableName -- 替换成实际表名 ) t WHERE t.RowNum = 1 ") .ToList();
内容的提问来源于stack exchange,提问作者Sina Hajian
相关产品推荐
相关产品推荐

