我正在收集一堆记录,每个记录都有一个时间戳。问题是我每秒收集大量记录,并且它们占用大量磁盘空间,并且当数据的使用时间超过一天时,我不需要这种粒度级别。我仍然想保留一些数据,比如说每秒大约一个记录,并删除所有其他数据。
例如:
Row TimeStamp(in seconds)
1 2
2 2.1 <--- delete
3 2.4 <--- delete
4 3
5 3.3 <--- delete
6 3.95
7 4.5 <--- delete
8 5.1
这样,我保留了大约一秒钟的记录,同时删除了两者之间的所有记录。有没有办法使用SQL做到这一点?
我想一种方法是遍历每一行并保持它们之间的全局时间戳差异,并在差异超过一秒时保存行,尽管我不确定如何在SQL中做到这一点。
答案 0 :(得分:1)
如果只需要保持固定的粒度,则可以使用日历槽位表(此处是使用generate_series
动态生成的),对于日历的每一行,请使用日期/时间功能。将这些行合并并分配给每个日历槽后,可以使用DISTINCT ON
根据任意表达式选择“最佳”行。像这样:
CREATE TEMP TABLE measurement (id integer, ts timestamp);
COPY measurement (id, ts) FROM STDIN;
1 2019-03-05 00:00:02
2 2019-03-05 00:00:02.1
3 2019-03-05 00:00:02.4
4 2019-03-05 00:00:03
5 2019-03-05 00:00:03.3
6 2019-03-05 00:00:03.95
7 2019-03-05 00:00:04.5
8 2019-03-05 00:00:05.1
\.
SELECT DISTINCT ON (day.ts) m.*
FROM (
SELECT '2019-03-05 00:00:00'::timestamp + (s||' seconds')::interval as ts
FROM generate_series(0, 86399) AS s
) AS day
JOIN measurement m
ON (m.ts > day.ts - '0.5 s'::interval
AND m.ts <= day.ts + '0.5 s'::interval)
ORDER BY day.ts, abs(extract(epoch from day.ts - m.ts))
;
/* result:
id | ts
----+------------------------
1 | 2019-03-05 00:00:02
4 | 2019-03-05 00:00:03
6 | 2019-03-05 00:00:03.95
8 | 2019-03-05 00:00:05.1
(4 rows)
*/
答案 1 :(得分:1)
我建议您仅每秒记录第一条。那应该是:
select distinct on (date_trunc('second', timestamp)) t.*
from t
order by date_trunc('second', timestamp), timestamp asc;
如果您的时间戳确实是数字,则可以使用:
select distinct on (trunc(timestamp)) t.*
from t
order by trunc(timestamp), timestamp;
Here是db <>小提琴。