Скажем, у меня есть одна таблица с двумя столбцами - customer_id и date:

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

Но, конечно, это синтаксически и логически не совсем там.

-1
KOB 21 Апр 2020 в 10:32

2 ответа

Из-за необходимости агрегировать в table2 на основе date из table1, это может быть проще написать как коррелированный подзапрос, чем 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)) 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

Демо на dbfiddle

0
Nick 21 Апр 2020 в 08:04

Если ваша (нераскрытая) СУБД поддерживает боковые объединения, вы можете сделать это:

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

Онлайн демо

0
a_horse_with_no_name 21 Апр 2020 в 08:38