2012-08-31 36 views
1

我正在嘗試編寫兩個表中的連接,其中左表中的日期值落入右表中的時間段。因此,舉例來說,如果我有:用歷史時間表連接表

TABLE A      TABLE B 
ID TIMESTMP    ID TIMESMTP    VALUE 
1  8/31/2012 2:00 PM  1  8/30/2012 4:00 AM A 
2  8/29/2012 3:00 PM  1  8/31/2012 1:00 PM B 
3  7/04/2012 5:00 AM  1  8/31/2012 3:00 PM C 
          2  8/20/2012 1:00 PM A 

結果應該是:

TABLE C      
ID TIMESTMP    VALUE 
1  8/31/2012 2:00 PM B 
2  8/29/2012 3:00 PM A  
3  7/04/2012 5:00 AM null 

我想找到表B中與最大時間戳這仍然是<表A中的時間戳相對應的記錄如果沒有匹配的id(外部連接),或者A中的時間戳B中沒有時間戳,它應該返回null。

謝謝!

UPDATE

這裏是我使用鉛()去的建議由戈登·利諾夫解決方案:

SELECT b.value, a.* 
    FROM table_a a 
    LEFT OUTER JOIN (
    SELECT id, timestmp, 
      lead(timestmp) over(PARTITION BY id ORDER BY timestmp) AS next_timestmp, 
      value FROM table_b 
    ) b 
    ON a.id = b.id 
    AND (a.timestmp >= b.timestmp AND (a.timestmp < b.timestmp OR b.timestmp IS NULL)) 

回答

1

您可以將其表示爲連接,但不能使用「=」。但是,有幫助的是每行都有下一個時間戳。這是鉛()函數就派上用場了:

select a.id, a.timestmp, b.value 
from A left outer join 
    (select b.*, 
      lead(timesmtp) over (partition by id order by timesmtp) as nextTS 
     from B 
    ) b 
    on a.id = b.id and 
     a.timestmp >= b.timesmtp and 
     a.timestmp < coalesce(nextTS, a.timestmp) 
+0

我非常喜歡這個想法。我不知道lead()函數。超級方便。然而,當我使用這個連接時,它減少了我的結果集(即使我做了一個正確的外連接)。 – Paul

+0

你應該嘗試一個左外連接。 。 。一個左外連接到B.這樣,你會保持在A中的一切。 –

+0

對不起,我的大腦向後。你是對的,左邊的外部連接給了我我所追求的。我最終做了一點改變,但lead()函數是關鍵。 – Paul

1

如果這是SQL Server的,我相信這可以用外實現所適用

SELECT A.id, A.timestmp, B.value FROM A OUTER APPLY (SELECT TOP 1 value FROM B WHERE id = A.id AND timesmtp < A.timestmp ORDER BY timesmtp DESC) B 
+0

我不認爲這是,這是一種恥辱,因爲這是整潔。 – podiluska

+0

這個問題被標記爲Oracle。 –

+0

糟糕,我的錯! –

2
with cte as 
(
select *, 
    ROW_NUMBER() over (partition by id order by timestmp) as rn 
from TableB 
) 

    select 
     v.id, v.timestmp, value 

    from 
    (  
    select a.id, a.timestmp, MAX(isnull(rn,1))rn 
    from TableA a 
     left join cte 
     on a.id = cte.id 
     and a.timestmp>cte.timestmp 
    group by a.id, a.timestmp 
    ) v 
     left join cte 
     on v.id = cte.id 
     and v.rn = cte.rn 
    order by v.id; 
+1

Oracle需要**語句後的語句終止字符**,而不是*之前的語句 –

0
select t.ID, t.Timestamp,B.Value 
from 
(
select A.ID, A.Timestamp, (SELECT max(B.TimeStamp) 
    FROM B where (B.Timestamp<A.Timestamp) and (B.id=A.Id) 
    ) max_date 

from A 
) t 
left join B on (t.max_date=B.TimeStamp) and (t.Id=B.ID)