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