【发布时间】:2019-09-10 21:12:49
【问题描述】:
编辑我的错,称为时间戳'日期'...
我们的数据表由时间戳、值和增量列组成。增量是自上次非空读数以来的分钟数。
CREATE TABLE Table1
("ts" timestamp with time zone, "value" numeric, "delta" int)
;
INSERT INTO Table1
("ts", "value", "delta")
VALUES
('2019-09-09 12:01:00', 3.5, NULL),
('2019-09-09 12:02:00', 3.2, 1),
('2019-09-09 12:03:00', NULL, 1),
('2019-09-09 12:04:00', 2.9, 2),
('2019-09-09 12:05:00', NULL, 1),
('2019-09-09 12:06:00', 3.0, 2),
('2019-09-09 12:07:00', NULL, 1),
('2019-09-09 12:08:00', NULL, 2),
('2019-09-09 12:09:00', NULL, 3),
('2019-09-09 12:10:00', NULL, 4),
('2019-09-09 12:11:00', 3.2, 5),
('2019-09-09 12:12:00', NULL, 1)
;
SELECT ts,
value,
delta,
FROM table
+---------------------+-------+-------+
| ts | value | delta |
+---------------------+-------+-------+
| 2019-09-09 12:01:00 | 3.5 | 1 |
| 2019-09-09 12:02:00 | 3.2 | 1 |
| 2019-09-09 12:03:00 | | 1 |
| 2019-09-09 12:04:00 | 2.9 | 2 |
| 2019-09-09 12:05:00 | | 1 |
| 2019-09-09 12:06:00 | 3.0 | 2 |
| 2019-09-09 12:07:00 | | 1 |
| 2019-09-09 12:08:00 | | 2 |
| 2019-09-09 12:09:00 | | 3 |
| 2019-09-09 12:10:00 | | 4 |
| 2019-09-09 12:11:00 | 3.2 | 5 |
| 2019-09-09 12:12:00 | | 1 |
+---------------------+-------+-------+
给定数据的子集,我们如何用最后一个非空值替换空值如果尚未选择替换值:
SELECT ts,
value,
delta,
FROM table
WHERE (/* expression giving us an arbitrary distribution of rows */)
+---------------------+-------+-------+
| ts | value | delta |
+---------------------+-------+-------+
| 2019-09-09 12:01:00 | 3.5 | |
| 2019-09-09 12:03:00 | | 1 |
| 2019-09-09 12:05:00 | | 1 |
| 2019-09-09 12:07:00 | | 1 |
| 2019-09-09 12:09:00 | | 3 |
| 2019-09-09 12:11:00 | 3.2 | 5 |
+---------------------+-------+-------+
我们想要:
+---------------------+-------+-------+
| ts | value | delta |
+---------------------+-------+-------+
| 2019-09-09 12:01:00 | 3.5 | |
| 2019-09-09 12:03:00 | 3.2 | 1 |
| 2019-09-09 12:05:00 | 2.9 | 1 |
| 2019-09-09 12:07:00 | 3.0 | 1 |
| 2019-09-09 12:09:00 | | 3 |<- an actual null
| 2019-09-09 12:11:00 | 3.2 | 5 |
+---------------------+-------+-------+
在这种情况下,行的分布是奇数;但是,这是任意的。我们不能使用感知到的日期频率模式来确定何时以及是否使用最后一个非空值。
到目前为止我们所做的尝试
作为第一步,继承所有最后的值。
WITH seq AS (
SELECT ts,
value,
delta,
ROW_NUMBER() OVER(ORDER BY date) AS row_no,
COUNT(*) OVER() AS total_count
FROM Table1
),
val AS (
SELECT ts,
value,
value_p,
first_value(value) over (partition by value_p order by date),
delta,
row_no,
total_count
FROM (
SELECT ts,
value,
delta,
row_no,
total_count,
sum(case when value is null then 0 else 1 end) over
(order by date) as value_p
FROM seq
ORDER BY ts
) as a
)
SELECT ts,
delta,
value,
case when value is null then first_value else value
end as cf
FROM val
| ts | delta | value | cf |
|---------------------|--------|--------|-----|
| 2019-09-09 12:01:00 | (null) | 3.5 | 3.5 |
| 2019-09-09 12:02:00 | 1 | 3.2 | 3.2 |
| 2019-09-09 12:03:00 | 1 | (null) | 3.2 |
| 2019-09-09 12:04:00 | 2 | 2.9 | 2.9 |
| 2019-09-09 12:05:00 | 1 | (null) | 2.9 |
| 2019-09-09 12:06:00 | 2 | 3 | 3 |
| 2019-09-09 12:07:00 | 1 | (null) | 3 |
| 2019-09-09 12:08:00 | 2 | (null) | 3 |
| 2019-09-09 12:09:00 | 3 | (null) | 3 |
| 2019-09-09 12:10:00 | 4 | (null) | 3 |
| 2019-09-09 12:11:00 | 5 | 3.2 | 3.2 |
| 2019-09-09 12:12:00 | 1 | (null) | 3.2 |
当我们为数据子集分配行时,我们现在既知道值又知道该值来自多少行。我们想不通的是,当我们通过 WHERE 生成子集时,如何确定是将值向前传递还是保留为 null。
如果解决方案不需要预定义的增量列,则奖励积分。
【问题讨论】: