在单查询中为多个父ID获取子表的最新单条明细记录
嘿,我来帮你搞定这个SQL查询的清晰实现方案~针对你要获取每个EVENT_ID对应的最新EVENT_DETAIL.TIME的DESCRIPTION字段值的需求,我整理了几种易懂且维护性强的写法,你可以根据自己的数据库版本来选:
方案一:使用窗口函数(首推,逻辑直白)
窗口函数是处理这类「分组取最新/最值」场景的最优解之一,代码逻辑清晰,后续维护起来也方便,适合MySQL 8+、PostgreSQL、SQL Server等绝大多数现代数据库:
SELECT e.EVENT_ID, ed.DESCRIPTION FROM Event e JOIN ( SELECT EVENT_ID, DESCRIPTION, TIME, -- 按事件ID分组,把每个组内的明细按时间倒序编号,最新的记录会拿到编号1 ROW_NUMBER() OVER (PARTITION BY EVENT_ID ORDER BY TIME DESC) AS record_rank FROM EVENT_DETAIL ) ed ON e.EVENT_ID = ed.EVENT_ID WHERE ed.record_rank = 1;
要是你的数据库支持FETCH FIRST 1 ROW WITH TIES(比如PostgreSQL、SQL Server),还能简化成更简洁的版本:
SELECT e.EVENT_ID, ed.DESCRIPTION FROM Event e JOIN EVENT_DETAIL ed ON e.EVENT_ID = ed.EVENT_ID ORDER BY ROW_NUMBER() OVER (PARTITION BY e.EVENT_ID ORDER BY ed.TIME DESC) FETCH FIRST 1 ROW WITH TIES;
方案二:关联子查询(兼容旧版本数据库)
如果你的数据库还不支持窗口函数(比如MySQL 5.x这类老版本),可以用关联子查询来实现:
SELECT e.EVENT_ID, ed.DESCRIPTION FROM Event e JOIN EVENT_DETAIL ed ON e.EVENT_ID = ed.EVENT_ID WHERE ed.TIME = ( -- 找到当前事件对应的最新明细时间 SELECT MAX(TIME) FROM EVENT_DETAIL WHERE EVENT_ID = e.EVENT_ID );
⚠️ 注意:如果同一个事件下有多个明细记录的时间完全相同(也就是并列最新),这个查询会返回多条记录。要是你想确保只取一条,可以在子查询里加额外的排序条件(比如明细的主键)来锁定唯一记录。
方案三:LATERAL JOIN(适合多字段场景)
如果之后你需要从明细表里取不止DESCRIPTION这一个字段,用LATERAL JOIN会更灵活,支持PostgreSQL、SQL Server等数据库:
SELECT e.EVENT_ID, latest_detail.DESCRIPTION FROM Event e LEFT JOIN LATERAL ( -- 对每个事件,找到时间最新的那条明细 SELECT DESCRIPTION FROM EVENT_DETAIL ed WHERE ed.EVENT_ID = e.EVENT_ID ORDER BY TIME DESC LIMIT 1 ) latest_detail ON true;
这里用LEFT JOIN是为了保证即使某个事件没有对应的明细记录,也能保留该事件的ID;如果不需要这种场景,换成普通JOIN就行。
你可以根据自己的数据库环境和实际数据情况挑选最合适的写法~
内容的提问来源于stack exchange,提问作者Aht
相关产品推荐
相关产品推荐

