SQL inner join on a column based on max value from another column
本问题已经有最佳答案,请猛点这里访问。
我有两个表,一个"主"是主列表的名称,第二个"方案"是主列表中每个名称的多个方案的列表。 我希望我的
1 2 3 4 5 6 | SELECT DISTINCT a.[USER], a.ID, a.Name, b.status FROM master a INNER JOIN scenario b ON a.ID = b.ID WHERE b.scenarioID = ( SELECT MAX(scenarioID) FROM scenario c2 WHERE c2.ID=c.ID) |
主
1 2 3 4 | ID USER Name 425 John Skyline 426 John Violin 427 Joe Pura |
脚本
1 2 3 4 5 6 7 | ID ScenarioID STATUS 425 1 active 425 2 active 425 3 done 426 1 active 426 2 active 427 1 done |
期望的输出
1 2 3 4 | ID USER Name STATUS 425 John Skyline done 426 John Violin active 427 Joe Pura done |
您可以使用
1 2 3 4 5 6 7 8 9 | SELECT M.ID, M.[USER], M.Name, X.Status FROM [Master] M CROSS Apply ( SELECT Top 1 S.Status FROM Scenario S WHERE S.ID = M.ID ORDER BY S.ScenarioID DESC ) X |
另一种方法是在
1 2 3 4 5 6 7 8 9 10 | ;WITH OrderedStatuses AS ( SELECT M.Id, M.[USER], M.Name, S.Status, ROW_NUMBER() OVER (Partition BY S.Id ORDER BY S.ScenarioID DESC) RN FROM [Master] M JOIN Scenario S ON S.Id = M.Id ) SELECT Id, [USER], Name, STATUS FROM OrderedStatuses WHERE RN = 1 |
这是一个略有不同的使用CTE的配方,我通常发现它比子查询更容易阅读(当然,你的里程可能会有所不同)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | DECLARE @Master TABLE ( ID BIGINT, [USER] VARCHAR(16), Name VARCHAR(16) ); DECLARE @Scenario TABLE ( ID BIGINT, ScenarioID BIGINT, [STATUS] VARCHAR(16) ); INSERT @Master VALUES (425, 'John', 'Skyline'), (426, 'John', 'Violin'), (427, 'Joe', 'Pura'); INSERT @Scenario VALUES (425, 1, 'active'), (425, 2, 'active'), (425, 3, 'done'), (426, 1, 'active'), (426, 2, 'active'), (427, 1, 'done'); WITH ReversedScenarioCTE AS ( SELECT ID, [STATUS], rowNumber = ROW_NUMBER() OVER (partition BY ID ORDER BY ScenarioID DESC) FROM @Scenario ) SELECT M.ID, M.[USER], M.Name, S.[STATUS] FROM @Master M INNER JOIN ReversedScenarioCTE S ON M.ID = S.ID AND S.rowNumber = 1; |
如果您有SQL Server 2008或更高版本,则可以使用ROW_NUMBER()函数来实现所需。 它将避免两次查询同一个表或执行连接。
1 2 3 4 5 6 7 8 9 10 11 | SELECT * FROM ( SELECT a.[USER] ,a.ID ,a.Name ,b.status ,ROW_NUMBER() OVER (PARTITION BY a.ID ORDER BY b.scenarioID DESC) AS VersionRank FROM [master] a INNER JOIN scenario b ON a.ID = b.ID ) RESULT WHERE RESULT.VersionRank = 1 |