能否使用Join与Group By优化指定SQL查询语句?
可以用JOIN + GROUP BY/窗口函数优化你的SQL查询
当然可以!你的这条查询用了关联子查询来获取每个Program的最新CurrentOwner,确实可以通过**JOIN + GROUP BY(或窗口函数)**的方式重构,通常这种写法在数据量较大时性能会更优——毕竟原查询里的子查询是对每一行Program_Master数据都单独执行一次TOP 1查询,重复执行的成本可不低。
优化方案1:使用窗口函数(更直观)
通过ROW_NUMBER()窗口函数给每个ProgramId下的记录按Id倒序排名,只保留排名第一的最新记录,再和主表关联:
SELECT PM.Program_ID, PM.[Program_Name], ISNULL(VF.ReadBy, 'NA') AS CurrentOwner FROM Program_Master PM LEFT JOIN ( SELECT ProgramId, ReadBy, ROW_NUMBER() OVER (PARTITION BY ProgramId ORDER BY Id DESC) AS rn FROM VVF_ScriptFlow ) VF ON PM.Program_ID = VF.ProgramId AND VF.rn = 1 WHERE PM.Department_ID = @DepartmentId;
优化方案2:使用GROUP BY + JOIN(兼容老版本SQL)
先通过GROUP BY找出每个ProgramId对应的最大Id(也就是最新记录的Id),再关联回VVF_ScriptFlow表拿到对应的ReadBy值:
SELECT PM.Program_ID, PM.[Program_Name], ISNULL(VF.ReadBy, 'NA') AS CurrentOwner FROM Program_Master PM LEFT JOIN ( SELECT s.ProgramId, s.ReadBy FROM VVF_ScriptFlow s INNER JOIN ( SELECT ProgramId, MAX(Id) AS MaxId FROM VVF_ScriptFlow GROUP BY ProgramId ) max_s ON s.ProgramId = max_s.ProgramId AND s.Id = max_s.MaxId ) VF ON PM.Program_ID = VF.ProgramId WHERE PM.Department_ID = @DepartmentId;
优化后的优势与注意事项
- 两种写法都避免了原查询中逐行执行子查询的开销,改为一次性处理所有
VVF_ScriptFlow数据,再和主表关联,数据量越大性能提升越明显。 - 为了让查询跑得更快,建议给
VVF_ScriptFlow表创建复合索引:CREATE INDEX IX_VVF_ScriptFlow_ProgramId_Id ON VVF_ScriptFlow(ProgramId, Id) INCLUDE(ReadBy);——这个索引能直接覆盖窗口函数或GROUP BY的查询需求,不用回表取数据。 - 两种方案都用了
LEFT JOIN,完全保留原查询的逻辑:即使某个Program没有对应的ScriptFlow记录,依然会返回'NA'作为CurrentOwner。
内容的提问来源于stack exchange,提问作者JTouchLogic
相关产品推荐
相关产品推荐

