Итак, мы немного поиграли и придумали следующий запрос, который, я думаю, выполнит то, что вы хотите:
with
__users as(
select distinct
user_id
from
dayload
)
select
row_number() over(order by __users.user_id asc, gs.date asc) as id,
gs.date::date,
__users.user_id,
coalesce(dayload.hours, max(hours) over(partition by __users.user_id order by gs.date asc), 0) as hours
from
generate_series('2018-01-01'::date, '2019-02-28'::date, interval '1 day') as gs("date")
cross join __users
left join dayload using(date, user_id)
order by
__users.user_id asc,
gs.date asc;
Объяснение запроса:
with
__users as(
select distinct
user_id
from
dayload
)
Это называется CTE, или c ommon t способны e xpression, упрощенное объяснение этого состоит в том, чтобы сказать, что это в основном встроенная временная таблицав данном контексте.Будьте осторожны, используя их, так как они хранятся исключительно в памяти, поэтому большие объемы возвращаемых данных могут вызвать чрезмерное разбиение на страницы, приводя вашу базу данных к обходу.
generate_series('2018-01-01'::date, '2019-02-28'::date, interval '1 day') as gs("date")
Это создает пустые даты между первым и вторым параметрами, передаваемыми вЗдесь вы определяете диапазон дат, по которому вы хотите выполнить запрос.
coalesce(dayload.hours, max(hours) over(partition by user_id order by date asc), 0) as hours
Это выборка часов в текущей строке, к которой мы присоединились в дневной загрузке.Если это значение равно NULL, то он выбирает наибольшие часы из дневной нагрузки, к которым присоединились предыдущие строки.Если это значение равно нулю, возвращается 0.
generate_series('2018-01-01'::date, '2019-02-28'::date, interval '1 day') as gs("date")
cross join __users
left join dayload using(date, user_id)
Сначала получает каждую дату между '2018-01-01' :: date и '2019-02-28' :: date, затем он пересекает соединенияна наш CTE ранее.
Перекрестное объединение объединит каждую запись из обеих таблиц вместе без фильтра.Это ситуативно полезно, но имейте в виду, что это даст количество записей в каждой таблице, умноженное вместе.Неосторожное использование может привести к большему количеству записей, чем у вашего сервера есть память.
После перекрестного соединения (с указанием каждой даты и каждого идентификатора пользователя) мы оставили присоединение к дневной загрузке.