如何通过SQL SELECT JOIN提取每个条目最新关联记录(禁用CTE/变量)
解决多表关联后获取每个Entry最新记录的方案(无CTE/变量)
嘿,这个问题我之前帮不少报表开发的朋友解决过——在不能用CTE或者变量的限制下,我们可以用分组子查询关联或者关联子查询过滤两种方式来实现,完全兼容普通SQL报表的需求。
方案一:分组子查询+关联过滤(推荐,性能更稳定)
核心思路是先通过分组找到每个entryID对应的最大主键记录,再把这个结果和原关联语句做一次关联,过滤出符合条件的单条最新记录。
假设WF_Progress表的主键是progressID(如果你的主键字段名不同,记得替换成实际名称),完整SQL如下:
SELECT -- 这里列出你需要的所有字段,比如ENT.*, ENTI.*, WFI.*, wfpg.* ENT.entryID, ENTI.instanceID, WFI.some_column, wfpg.progressID, wfpg.operator_name -- 比如你提到的Charlie FROM ENT LEFT JOIN ENT_Instance ENTI ON ENT.entryID = ENTI.entryID LEFT JOIN VW_Instance WFI ON ENTI.instanceID = WFI.instanceID LEFT JOIN WF_Progress wfpg ON WFI.instanceID = wfpg.instanceID -- 关联子查询:找到每个entry对应的最大主键记录 INNER JOIN ( SELECT ENT.entryID, MAX(wfpg.progressID) AS max_progressID FROM ENT LEFT JOIN ENT_Instance ENTI ON ENT.entryID = ENTI.entryID LEFT JOIN VW_Instance WFI ON ENTI.instanceID = WFI.instanceID LEFT JOIN WF_Progress wfpg ON WFI.instanceID = wfpg.instanceID GROUP BY ENT.entryID ) AS latest_entry ON ENT.entryID = latest_entry.entryID AND (wfpg.progressID = latest_entry.max_progressID OR wfpg.progressID IS NULL)
关键点说明:
- 子查询通过
GROUP BY ENT.entryID和MAX(wfpg.progressID),为每个entry锁定了最新的那条记录的主键值; - 最后的
OR wfpg.progressID IS NULL是为了保留那些没有对应进度记录的entry,避免过滤掉原本的空值结果; - 如果你的主键不是
progressID,把所有progressID替换成实际的主键字段即可。
方案二:WHERE子句关联子查询(写法更简洁)
如果你的数据量不大,也可以直接在WHERE子句里用关联子查询来过滤,判断当前记录的主键是否是该entry下的最大值:
SELECT -- 列出你需要的字段 ENT.entryID, ENTI.instanceID, WFI.some_column, wfpg.progressID, wfpg.operator_name FROM ENT LEFT JOIN ENT_Instance ENTI ON ENT.entryID = ENTI.entryID LEFT JOIN VW_Instance WFI ON ENTI.instanceID = WFI.instanceID LEFT JOIN WF_Progress wfpg ON WFI.instanceID = wfpg.instanceID WHERE wfpg.progressID IS NULL OR wfpg.progressID = ( SELECT MAX(wfpg2.progressID) FROM ENT AS ENT2 LEFT JOIN ENT_Instance ENTI2 ON ENT2.entryID = ENTI2.entryID LEFT JOIN VW_Instance WFI2 ON ENTI2.instanceID = WFI2.instanceID LEFT JOIN WF_Progress wfpg2 ON WFI2.instanceID = wfpg2.instanceID WHERE ENT2.entryID = ENT.entryID )
关键点说明:
- 子查询会针对每一条外层的记录,找到对应entry的最大主键值,然后匹配当前记录;
wfpg.progressID IS NULL同样是为了保留无进度记录的entry;- 这种写法更直观,但数据量大的时候性能可能不如方案一,报表场景下如果数据量不大完全可以用。
两种方案都不需要CTE或者变量,直接在普通SQL里就能运行,完美适配你的报表需求。
内容的提问来源于stack exchange,提问作者Wimpie Norman
相关产品推荐
相关产品推荐

