使用历史时间轴连接表格

时间:2012-08-31 14:19:31

标签: sql oracle join oracle10g

我试图在两个表之间写一个连接,其中左表中的日期值落入右表的一个时隙。所以,例如,如果我有:

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(外连接)或者B中没有时间戳。在A中的时间戳,它应该返回null。

谢谢!

更新

以下是Gordon Linoff建议使用lead()的解决方案:

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))

4 个答案:

答案 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 :(得分: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

答案 2 :(得分:1)

您可以将此表达为联接,但不能使用“=”。但是,有用的是每行上有下一个时间戳。这是lead()函数派上用场的地方:

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)

答案 3 :(得分: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)