【问题标题】:Joining tables with a historical timeline使用历史时间线连接表
【发布时间】:2012-08-26 09:15:15
【问题描述】:

我正在尝试编写两个表之间的连接,其中左表中的日期值落入右表的时隙。因此,例如,如果我有:

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中找到对应的记录,最大时间戳仍然是

谢谢!

更新

这是我按照 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))

【问题讨论】:

    标签: sql oracle join oracle10g


    【解决方案1】:
    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;
    

    【讨论】:

    • Oracle需要语句终止符语句之后,而不是之前语句
    【解决方案2】:

    您可以将其表示为连接,但不能使用“=”。但是,有帮助的是在每一行上都有下一个时间戳。这就是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)
    

    【讨论】:

    • 我真的很喜欢这个主意。我不知道lead() 函数。超级好用。但是,当我使用此连接时,它会减少我的结果集(即使我进行了右外连接)。
    • 你应该尝试左外连接。 . . B 的左外连接。这样,您将把所有内容都保留在 A 中。
    • 对不起,我的大脑倒退了。你是对的,左外连接给了我我想要的东西。我最终做了一些不同的事情,但是lead() 函数是关键。
    【解决方案3】:

    如果这是 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
    

    【讨论】:

    • 我不这么认为,这很可惜,因为那很整洁。
    • 该问题使用 Oracle 标记。
    【解决方案4】:
    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)
    

    【讨论】:

      猜你喜欢
      • 2018-11-25
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 2015-06-29
      • 2011-09-05
      • 2013-10-23
      • 2016-04-18
      相关资源
      最近更新 更多