2012-08-31 35 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)