1

I'm trying to write a join bewteen two tables where a date value in the left table falls into a time slot on the right table. So, for example if I have:

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

The result should be:

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  

I want to find the corresponding record in table B with the max timestamp which is still < the timestamp in table A. If there is not a matching id (outer join) or there are no timestamps in B < the timestamp in A, it should return null.

Thanks!

UPDATE

Here is the solution I went with using lead() as suggested by Gordon Linoff:

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

4 回答 4

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;
于 2012-08-31T14:39:34.990 回答
1

如果这是 sql server 我相信这可以通过外部应用来实现

IE

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
于 2012-08-31T14:38:09.287 回答
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)
于 2012-08-31T14:39:51.373 回答
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)
于 2012-08-31T14:52:59.737 回答