You can solve this problem with the ROW_NUMBER() function:
SELECT RefID, intVal, NextGt, SomeVal, FROM ( SELECT t2.RefID, t2.intVal, t1.intVal AS NextGt, t1.SomeVal, ROW_NUMBER() OVER (PARTITION BY t2.RefID, t2.intVal ORDER BY t1.intVal) AS rn FROM dbo.Table2 AS t2 LEFT JOIN dbo.Table1 AS t1 ON t1.RefID = t2.RefID AND t1.intVal >= t2.intVal ) s WHERE rn = 1 ;
The derived table corresponds to each row of Table2 with all rows of Table1 that have the same RefID and intVal , which is greater than or equal to Table2.intVal . Each subset of matches is ranked, and the first row is returned by the main query.
A nested query uses an outer join, so those Table2 rows that do not have Table1 matches are still returned (with zeros replaced by Table1 columns).
Alternatively, you can use OUTER APPLY :
SELECT t2.RefID, t2.intVal, t1.intVal AS NextGt, t1.SomeVal FROM dbo.Table2 AS t2 OUTER APPLY ( SELECT TOP (1) t1.intVal FROM dbo.Table1 AS t1 WHERE t1.RefID = t2.RefID AND t1.intVal >= t2.intVal ORDER BY t1.intVal ASC ) AS t1 ;
This method is simpler: for each row of Table2 get all the matches from Table1 based on the same set of conditions, sort the matches in ascending order of Table1.intVal and take the top intVal .
source share