Объединить и объединить, где дата в правой таблице <= дата в левой таблице - PullRequest
0 голосов
/ 21 апреля 2020

Скажем, у меня есть одна таблица с двумя столбцами - 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    

Как я могу это сделать? Моя первоначальная идея логики c будет выглядеть примерно так:

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

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

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

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

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 голосов
/ 21 апреля 2020

Из-за необходимости агрегировать в 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), 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

Демонстрация на dbfiddle

...