SQL,连接表

时间:2016-02-08 07:01:46

标签: sql join teradata

这是一个问题。我们有两个表A和B.两个都有一个Date类型的字段。相应地将它们表示为Date_A和Date_B。问题是通过以下方法将这两个表相互连接 - 来自表A的每一行X我们需要从B连接到某些行Y,使得从B行Y中的所有行Z中提供表达式abs的最小值(Date_A(X)-Date_B(Z)),即它在Date_B中的值是最接近X中Date_A的值。假设这个最小值始终是唯一的,但如果不是,那么随机选择其中一个是好的(但是只有一个)。 例。 表A:

"A", "B", "2015-10-01"

表B: "C", "2015-10-07" "D", "2015-12-02"

预期结果:

"A", "B", "2015-10-01", "C", "2015-10-07"

P.S。如果重要的话,该平台是Teradata

1 个答案:

答案 0 :(得分:1)

当然你可以根据你的逻辑编写一个连接条件,但是像Teradata这样的并行DBMS中的这个最坏的情况。它总是会产生一个产品连接(可能后跟另一个步骤只返回一个匹配的行)。

对于最接近匹配连接,我通常会尝试使用LAG / LEAD逻辑找到实际值:

SELECT
  dt as date_A,
  -- find the previous date_B // LAG
  MAX(CASE WHEN x = 2 THEN dt end) OVER (ORDER  BY dt, x ROWS UNBOUNDED PRECEDING ) AS prev_date,
  -- find the next date_B // LEAD
  MIN(CASE WHEN x = 2 THEN dt end) OVER (ORDER  BY dt, x ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS next_date,
  -- now find the nearest date
  CASE WHEN prev_date IS NULL THEN next_date
       WHEN next_date IS NULL THEN prev_date
       WHEN dt - prev_date < next_date - dt THEN prev_date 
       ELSE next_date 
  END AS date_B
FROM
 ( -- get all dates, maybe UNION INSTEAD OF UNION ALL
   SELECT date_A as dt, 1 AS x
   FROM table_A
   UNION ALL
   SELECT date_B, 2
   FROM table_B
 ) AS dt
QUALIFY x = 1 -- only rows from table_A

这需要两个STAT步骤,但现在你得到了正确的date_B到equi-join。将它放在派生表中并加入table_Atabke_B,除非两个表都非常小,否则应该快得多。

当然你也可能加入其他列,所以将它们添加到UNION和PARTITON BY。