Исторический баланс из таблицы транзакций

#postgresql

Вопрос:

У меня есть следующая таблица:

идентификатор пользователя дата совершения сделки day_end_balance
523161 7/2/2021 136.2
523161 6/14/2021 215.4
523161 6/7/2021 0
523161 6/2/2021 440

Таким образом, баланс отображается при совершении транзакции, и баланс остается неизменным в конце дня, если транзакция не происходит. Я хочу создать таблицу, которая показывает баланс на конец дня на одного клиента с начала жизни клиента до сегодняшнего дня. Проверьте приведенную ниже таблицу для получения желаемого результата.

идентификатор пользователя дата совершения сделки day_end_balance
523161 6/2/2021 440
523161 6/3/2021 440
…… ………… …..
523161 6/7/2021 0
523161 6/8/2021 0
523161 6/9/2021 0
523161 6/10/2021 0
523161 6/11/2021 0
523161 6/12/2021 0
523161 6/13/2021 0
523161 6/14/2021 215.4
523161 6/14/2021 215.4
523161 6/15/2021 215.4
523161 6/16/2021 215.4
523161 6/17/2021 215.4
523161 6/18/2021 215.4
523161 6/19/2021 215.4
523161 6/20/2021 215.4
523161 6/21/2021 215.4
523161 6/22/2021 215.4
523161 6/23/2021 215.4
523161 6/24/2021 215.4
523161 6/25/2021 215.4
523161 6/26/2021 215.4
523161 6/27/2021 215.4
523161 6/28/2021 215.4
523161 6/29/2021 215.4
523161 6/30/2021 215.4
523161 7/1/2021 215.4
523161 7/2/2021 136.2
523161 …. 136.2
523161 дата сегодняшнего дня 136.2

Как это сделать в postgres sql? Я знаю, что это будет включать last_value() и coalesce (), и, возможно, lag() и lead(). Но не знаю, как это написать.

Ответ №1:

generate_series() Вы можете использовать, чтобы получить все дни между минимальным днем для клиента и сегодняшним днем, и присоединиться к этому, выбрав данные самого верхнего дня, меньшего или равного соответствующему дню в серии.

 SELECT cjl."customer_id",
       gs."transacting date",
       cjl."day_end_balance"
       FROM generate_series((SELECT min(t."transacting date")
                                    FROM elbat t
                                    WHERE t."customer_id" = 523161),
                            current_date,
                            '1 day'::interval) gs
                                               ("transacting date")
            CROSS JOIN LATERAL (SELECT t."customer_id",
                                       t."day_end_balance"
                                       FROM elbat t
                                       WHERE t."customer_id" = 523161
                                             AND t."transacting date" <= gs."transacting date"
                                       ORDER BY t."transacting date" DESC
                                       LIMIT 1) cjl
       ORDER BY gs."transacting date";