【问题标题】:Join and aggregate where date in right table <= date in left table加入并聚合右表中的日期 <= 左表中的日期
【发布时间】:2020-08-03 21:09:48
【问题描述】:

假设我有一张有两列的表 - customer_iddate

customer_id          date
          1    2020-01-29
          1    2020-03-14
          2    2020-04-05
          2    2020-02-18

我有另一个表格显示客户购买的日期和金额:

customer_id          date    amount
          1    2019-12-03        10
          1    2020-01-30        20
          1    2020-03-10        30
          1    2020-03-18        40
          2    2020-02-29        50 
          2    2020-03-10        60
          2    2020-04-01        70

我现在想在第一个表和第二个表上进行连接,创建一个新列,显示第一个表的每一行上迄今为止的购买金额的总和:

customer_id          date    amount_td
          1    2020-01-29           10
          1    2020-03-14           60
          2    2020-04-05          180
          2    2020-03-20          110    

我该怎么做?我最初对逻辑的想法是这样的:

SELECT
    table1.customer_id,
    table1.date,
    table2_agg as amount_td
FROM
    table1
LEFT JOIN (
    SELECT
        customer_id,
        SUM(amount)
    FROM
        table2
    HAVING
        table2.date <= table1.date
) table2_agg
ON
    table1.customer_id = table2_agg.customer_id

当然,这在语法和逻辑上并不完全存在。

【问题讨论】:

  • 还不错。您的子查询需要一个 GROUP BY。 HAVING 应该在 WHERE。 SUM() 列需要一个名称。
  • 您使用的是哪个 dbms?
  • 对不起,我复制粘贴到这里时错过了组。我正在使用 Presto,但我什至没有尝试运行这个想法,因为我对逻辑有点偏离

标签: sql join group-by aggregate-functions presto


【解决方案1】:

由于需要基于来自table1datetable2 中进行聚合,这可能比JOIN 更容易编写为相关子查询:

SELECT
    table1.customer_id,
    table1.date,
    COALESCE((SELECT SUM(amount) AS amount 
              FROM table2
              WHERE table2.date <= table1.date AND
                    table2.customer_id = table1.customer_id), 0) AS amount
FROM
    table1

您也可以将其写为JOIN,但聚合需要发生在查询的顶层:

SELECT
    table1.customer_id,
    table1.date,
    COALESCE(SUM(table2.amount), 0) AS amount
FROM
    table1
LEFT JOIN 
    table2 ON table2.customer_id = table1.customer_id
          AND table2.date <= table1.date
GROUP BY table1.customer_id, table1.date

无论哪种情况,输出都是:

customer_id     date        amount
1               2020-01-29  10
1               2020-03-14  60
2               2020-04-05  180
2               2020-03-20  110

Demo on dbfiddle

【讨论】:

    【解决方案2】:

    如果您的(未公开)DBMS 支持横向连接,您可以这样做:

    select t1.*, t.amount
    from table1 t1
      left join lateral (
         select t2.customer_id, sum(t2.amount) as amount
         from table2 t2
         where t2.customer_id = t1.customer_id
           and t2.date <= t1.date
         group by t2.customer_id
      ) as t on true
    

    Online demo

    【讨论】:

      猜你喜欢
      • 2019-09-21
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多