我有一个表dayload,用于标记用户每天的工作时间何时发生变化。
| id | date | user_id | hours |
| 1 | 2019-01-27 | 1 | 4 |
| 2 | 2019-02-01 | 1 | 8 |
| 3 | 2018-06-30 | 2 | 5 |
| 4 | 2018-07-02 | 2 | 8 |
因此该表仅跟踪更改。我想要得到的是一系列连续的日期以及当前有效的时间。
例如我想知道 2018-01-01 到 2019-02-28 之间每个用户和日期的工作时间,即
| id | date | user_id | hours |
| .. | 2018-01-27 | 1 | 4 |
| .. | 2018-01-28 | 1 | 4 |
| .. | 2018-01-29 | 1 | 4 |
| .. | 2018-01-30 | 1 | 4 |
| .. | 2018-01-31 | 1 | 4 |
| .. | 2019-02-01 | 1 | 8 |
| .. | 2019-02-02 | 1 | 8 |
| .. | 2019-02-03 | 1 | 8 |
| .. | 2019-02-04 | 1 | 8 |
...
| .. | 2018-06-30 | 2 | 5 |
| .. | 2018-07-01 | 2 | 5 |
| .. | 2018-07-02 | 2 | 8 |
| .. | 2018-07-03 | 2 | 8 |
...
我不知道如何填空,正如我所描述的那样。我考虑过创建一个只包含 1900 年到 2100 年之间日期的表,但我想不出如何使用日期表来填充空白。
我读过有关generate_series的内容,我尝试过以不同的方式加入数据,我还尝试使用PostgresSQL的窗口函数。但我不知道怎么办。
我与日期表最接近,但问题是如果用户的最新行的日期超出我想要查询的范围,则不会显示在结果中。这是我尝试过的查询:
SELECT user_id, d.date, minutes
FROM day d
JOIN dayload dl
ON dl.date = (
SELECT MAX(date) from DAYLOAD where date <= d.date
)
order by d.date;
我将用户表等加入到此关系中,但是当我将日期范围过滤应用于查询时,那些具有日期范围之外的最新日负载的行将被遗漏。
最佳答案
我认为这符合你的要求:
select generate_series(date,
lead(date, 1, current_date) over (partition by user_id order by date) - interval '1 day',
interval '1 day'
) as date,
user_id, hours
from (values (1, '2019-01-27'::date, 1, 4),
(2, '2019-02-01'::date, 1, 8),
(3, '2018-06-30'::date, 2, 5)
) v(id, date, user_id, hours);
这是一个generate_series()
的“简单”应用程序。 lead()
正在获取用户的下一个日期。减去一天的复杂性以及所有这些,这样日子就不会重叠。
Here是一个数据库<> fiddle 。
关于sql - 在 PostgreSQL 中用每个用户的最新值填充缺失的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54909729/