【发布时间】:2020-12-05 20:57:34
【问题描述】:
我的挑战是找到按时间戳相邻的行对,并仅保留值字段距离最小的行对(差异的正值)
一张表measurement 收集来自不同传感器的带有时间戳和值的数据。
id | sensor_id | timestamp | value
---+-----------+-----------+------
1 | 1 | 12:00:00 | 5
2 | 2 | 12:01:00 | 6
3 | 1 | 12:02:00 | 4
4 | 2 | 12:02:00 | 7
5 | 2 | 12:03:00 | 3
6 | 1 | 12:05:00 | 3
7 | 2 | 12:06:00 | 4
8 | 2 | 12:07:00 | 5
9 | 1 | 12:08:00 | 6
传感器的值从其时间戳开始有效,直到其下一条记录的时间戳(相同的 sensor_id)。
图形表示
下方的绿线显示传感器 1(蓝线)和传感器 2(红线)值随时间变化的距离。
我的目标是
- 仅合并 2 个与时间戳逻辑匹配的传感器的记录(获得绿线)
- 找到 dinstance 局部最小值
- 12:01:00(12:00:00 没有传感器 2 的记录)
- 12:05:00
- 12:08:00
真实表位于 PostgreSQL 数据库中,包含 15 个传感器的大约 500 万条记录。
测试数据
create table measurement (
id serial,
sensor_id integer,
timestamp timestamp,
value integer)
;
insert into measurement (sensor_id, timestamp, value)
values
(1, '2020-08-16 12:00:00', 5),
(2, '2020-08-16 12:01:00', 6),
(1, '2020-08-16 12:02:00', 4),
(2, '2020-08-16 12:02:00', 7),
(2, '2020-08-16 12:03:00', 3),
(1, '2020-08-16 12:05:00', 3),
(2, '2020-08-16 12:06:00', 4),
(2, '2020-08-16 12:07:00', 5),
(1, '2020-08-16 12:08:00', 6)
;
我的方法
是选择 2 个任意传感器(通过某些 sensor_ids),进行自连接并为任何传感器 1 的记录保留仅具有先前时间戳的传感器 2 的记录(传感器 2 的最大时间戳和传感器 1 的时间戳
select
*
from (
select
*,
row_number() over (partition by m1.timestamp order by m2.timestamp desc) rownum
from measurement m1
join measurement m2
on m1.sensor_id <> m2.sensor_id
and m1.timestamp >= m2.timestamp
--arbitrarily sensor_ids 1 and 2
where m1.sensor_id = 1
and m2.sensor_id = 2
) foo
where rownum = 1
union --vice versa
select
*
from (
select
*,
row_number() over (partition by m2.timestamp order by m1.timestamp desc) rownum
from measurement m1
join measurement m2
on m1.sensor_id <> m2.sensor_id
and m1.timestamp <= m2.timestamp
--arbitrarily sensor_ids 1 and 2
where m1.sensor_id = 1
and m2.sensor_id = 2
) foo
where rownum = 1
;
但这会返回一对12:00:00,其中传感器 2 没有数据(不是大问题)
并且在真实表上,语句执行不会在数小时后结束(大问题)。
我发现了一些类似的问题,但它们与我的问题不符
提前致谢!
【问题讨论】:
-
你可能会遇到稳定的婚姻问题,比如并发症。
标签: sql postgresql datetime window-functions