【问题标题】:How to join two tables with multiple matching records?如何连接具有多个匹配记录的两个表?
【发布时间】:2018-04-18 05:24:16
【问题描述】:

当 id 和日期对齐时,我想加入两个表。我在想这样的事情:

SELECT * from t1 inner join t2 on t1.id = t2.id and t1.date >= t2.date;

但是每个 id 的多个条目可能存在于两个表中,我想确保最佳记录匹配 - 所以如果表 2 有 4/10、4/15 和 4/20 的条目,并且表 1 有 3/15、4/11、4/16 和 4/21 的记录,那么这些记录将匹配如下:

id | t1.date | t2.date
1  |   3/15  | -----  (No match, wouldn't be returned in the results)
1  |   4/11  | 4/10
1  |   4/16  | 4/15
1  |   4/21  | 4/20

【问题讨论】:

  • 在 t1 和 t2 日期之间创建一个 datediff,然后为每场比赛取最小值
  • 我正在使用 Postgres。使用 datediff 会是什么样子?

标签: sql postgresql


【解决方案1】:

一种方法是left joinidt1.date >= t2.date 上的表,在合适的有序分区(t1.date - t2.date)上使用窗口函数row_number(),并选择最小的日期差异是第一个分区行:

CREATE TABLE t1 ("id" integer, "date" date, "value" integer);

CREATE TABLE t2 ("id" integer, "date" date);

INSERT INTO t1 VALUES
  (1, '2018-03-15', 10),
  (1, '2018-04-11', 20),
  (1, '2018-04-11', 30),
  (1, '2018-04-16', 30),
  (1, '2018-04-21', 20);

INSERT INTO t2 VALUES
  (1, '2018-04-10'),
  (1, '2018-04-15'),
  (1, '2018-04-20');

WITH q AS (
  SELECT
    t1."id", t1."date" t1_date, t2."date" t2_date, t1."value", row_number() OVER
      (PARTITION BY t1."id", t1."date", t1."value" ORDER BY (t1."date" - t2."date")) row_num
  FROM
    t1 LEFT JOIN t2 ON t1."id" = t2."id" AND t1."date" >= t2."date"
)
SELECT "id", "t1_date", "t2_date", "value" FROM q
WHERE row_num = 1;

--  id |  t1_date   |  t2_date   | value 
-- ----+------------+------------+-------
--   1 | 2018-03-15 |            |    10
--   1 | 2018-04-11 | 2018-04-10 |    20
--   1 | 2018-04-11 | 2018-04-10 |    30
--   1 | 2018-04-16 | 2018-04-15 |    30
--   1 | 2018-04-21 | 2018-04-20 |    20
-- (5 rows)

请注意,如果您希望结果数据集排除 t2.date 不匹配的行,只需将 LEFT JOIN 替换为 INNER JOIN

【讨论】:

  • @st2 tas,如果我正确理解您的新要求,您只需对附加字段进行分区,如我修改后的答案所示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
相关资源
最近更新 更多