2012-05-24 100 views
4

給出下面的表1:下一最小值,大於或等於獲取給定值的每個組

RefID intVal SomeVal 
    ---------------------- 
     1  10 val01 
     1  20 val02 
     1  30 val03 
     1  40 val04 
     1  50 val05 
     2  10 val06 
     2  20 val07 
     2  30 val08 
     2  40 val09 
     2  50 val10 
     3  12 val11 
     3  14 val12 
     4  10 val13 
     5  100 val14 
     5  150 val15 
     5 1000 val16 

和表2含有一些RefIDs和intVals等

RefID intVal 
    ------------- 
     1  11  
     1  28  
     2  9  
     2  50  
     2  51  
     4  11  
     5  1  
     5  150  
     5  151  

需要SQL語句來獲得下一個更大的int值,每個RefID和NULL如果在Table1中找不到,則爲NULL 以下是預期結果

RefID intVal nextGt SomeVal 
    ------------------------------ 
     1  11  20 val01 
     1  28  30 val03 
     2  9  10 val06 
     2  50  50 val10 
     2  51 NULL NULL 
     4  11 NULL NULL 
     5  1  100 val14 
     5  150  150 val15 
     5  151 1000 val16 

幫助將不勝感激!

+3

您正在使用哪些DBMS? PostgreSQL的?甲骨文? DB2?火鳥? –

+0

你有什麼嘗試? –

回答

7

派生表a從表1中檢索表1給出的最小值refidintVal;外部查詢僅檢索someValue。

select a.refid, a.intVal, a.nextGt, table1.SomeVal 
from 
(
    select table2.refid, table2.intval, min (table1.intVal) nextGt 
     from table2 
     left join table1 
     on table2.refid = table1.refid 
     and table2.intVal <= table1.intVal 
    group by table2.refid, table2.intval 
) a 
-- table1 is joined again to retrieve SomeVal 
left join table1 
    on a.refid = table1.refid 
and a.nextGt = table1.intVal 

Here is Sql Fiddle with live test

+0

+1,正是我想的那麼想過沒有發佈.... – Addicted

3

就可以解決這個使用ROW_NUMBER()功能:

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 
; 

派生表中的每一行Table2匹配與具有相同RefIDintVal大於或等於Table2.intVal所有Table1行。每個匹配的子集都進行了排名,並且主查詢返回了第一行。

嵌套查詢使用外部聯接,因此仍然返回那些沒有Table1匹配的行Table2(用空值代替Table1列)。

或者您可以使用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 
; 

這種方法可以說是更簡單:每個Table2行,得到基於同一組條件Table1所有的比賽,比賽中的升序排序Table1.intVal並取頂部intVal

0

這可以用由聯接,組和一個case語句,和一個特技來完成:

select t1.refid, t2.intval, 
     min(case when t1.intval > t2.intval then t1.intval end) as min_greater_than_ref, 
     substring(min(case when t1.intval > t2.intval 
          then right('00000000'+cast(t1.intval as varchar(255)), 8)+t1.SomeVal) 
        end)), 9, 1000) 
from table1 t1 left join 
    table2 t2 
    on t1.refid = t2.refid 
group by t1.refid, t2.intval 

SO,關鍵是要預先考慮整數值來someValue中,零填充的整數值(在這種情況下爲8個字符)。你會得到類似於:「00000020val01」。此列的最小值基於整數的最小值。最後一步是提取值。

對於本示例,我使用SQL Server語法進行串聯。在其他數據庫中,您可以使用CONCAT()或||。

相關問題