【发布时间】:2019-03-27 21:39:37
【问题描述】:
我正在尝试针对版本化时间序列表编写一个 postgres 查询,以获取可用数据的最新版本。
我开始尝试在每个时间戳获取最新版本,但这给了我一个问题,即时间戳的偏移量或不同的收集频率会在最终结果中将版本交错在一起。一个例子是数据间隔是每两分钟,并且每分钟收集一次。下面是不同间隔的另一个示例。如果需要,我可以在客户端完成此操作,但我认为如果我可以在 SQL 端完成它会更好。
这是我现有的具有交错问题的查询。它也不是性能最高的,但我看不到将 CTE 推送到视图的方法,因为该视图没有日期过滤器,这在此表上非常有用。
-- Current SQL query, not very fast
WITH version_ranked AS (
SELECT
tv.timeseries_id
, tv.value_number
, tv.value_time
, tv.version_time
, RANK() over (PARTITION BY tv.timeseries_id, tv.value_time ORDER BY tv.version_time DESC) AS rn
FROM timeseries_values AS tv
WHERE tv.timeseries_id = @id
AND version_time > @time_filter
)
SELECT
*
FROM version_ranked AS vr
WHEREv r.rn = 1
-- Sample table, with an extra row between versions
| timeseries_id (int) | value_number (numeric) | value_time (datetime) | version_time (datetime) |
| 1 | 30 | '2019-03-27 00:03:00' | '2019-03-26 00:00:00' |
| 1 | 20 | '2019-03-27 00:02:00' | '2019-03-26 00:00:00' |
| 1 | 10 | '2019-03-27 00:01:00' | '2019-03-26 00:00:00' |
| 1 | 3 | '2019-03-27 00:01:30' | '2019-03-25 00:00:00' |
| 1 | 2 | '2019-03-27 00:01:00' | '2019-03-25 00:00:00' |
| 1 | 1 | '2019-03-27 00:00:30' | '2019-03-25 00:00:00' |
-- What I get with above code, interleaving the versions
| timeseries_id (int) | value_number (numeric) | value_time (datetime) | version_time (datetime) |
| 1 | 30 | '2019-03-27 00:03:00' | '2019-03-26 00:00:00' |
| 1 | 20 | '2019-03-27 00:02:00' | '2019-03-26 00:00:00' |
| 1 | 3 | '2019-03-27 00:01:30' | '2019-03-25 00:00:00' |
| 1 | 10 | '2019-03-27 00:01:00' | '2019-03-26 00:00:00' |
| 1 | 1 | '2019-03-27 00:00:30' | '2019-03-25 00:00:00' |
--What I want in the end
| timeseries_id (int) | value_number (numeric) | value_time (datetime) | version_time (datetime) |
| 1 | 30 | '2019-03-27 00:03:00' | '2019-03-26 00:00:00' |
| 1 | 20 | '2019-03-27 00:02:00' | '2019-03-26 00:00:00' |
| 1 | 10 | '2019-03-27 00:01:00' | '2019-03-26 00:00:00' |
| 1 | 1 | '2019-03-27 00:00:30' | '2019-03-25 00:00:00' |
【问题讨论】:
-
为什么 "value_number"=3 没有出现在你想要的东西上?
-
因为它来自以前的版本,并且将该值内插到 15 而不是取旧值 3 更有效。在这个例子中它不太明显,但这里有很多用例是几个小时的预测,这些预测可能会随着新信息的不同而有很大差异。因此,最新版本是该版本中从第一个时间戳到最后一个时间戳的最佳事实来源,但一旦超出该版本,前一个就是最佳来源。
-
在查询中,分区中有一个 ORDER BY tv.version_time DESC。对于所需的输出,只需在查询中按 ORDER BY value_time 即可。顺便说一句,这里不需要 CTE 表。
-
使用查询
SELECT tv.timeseries_id , tv.value_number , tv.value_time , tv.version_time , RANK() over (PARTITION BY tv.timeseries_id, tv.value_time ORDER BY tv.value_time) AS rn FROM temp_table AS tv给了我相同排名的所有内容,所以这并没有给我想要的输出。如果我弄错了,您可以发布您的意思吗?