在一个时间间隔内生成时间戳范围并查询所有重叠事件
Generate timestamp ranges over an interval and query for all overlapping events
我想在一个时间间隔内生成一系列时间戳范围,并为所有重叠事件查询 table。我 几乎 在那里,但对 SQL 还是很陌生,似乎无法克服这个困难。
为了测试,我构建了一个 table 包含一系列事件,每个事件都发生在一个日期时间范围内:
CREATE TABLE event (id int, order_dates tsrange, flow int);
INSERT INTO event VALUES
(1,'[2021-09-01 10:55:01,2021-09-04 15:16:01)',50),
(2,'[2021-08-15 20:14:27,2021-08-18 22:19:27)',36),
(3,'[2021-08-03 12:51:47,2021-08-05 11:28:47)',41),
(4,'[2021-08-17 09:14:30,2021-08-20 13:57:30)',29),
(5,'[2021-08-02 20:29:07,2021-08-04 19:19:07)',27),
(6,'[2021-08-26 02:01:13,2021-08-26 08:01:13)',39),
(7,'[2021-08-25 23:03:25,2021-08-27 03:22:25)',10),
(8,'[2021-08-12 23:40:24,2021-08-15 08:32:24)',26),
(9,'[2021-08-24 17:19:59,2021-08-29 00:48:59)',5),
(10,'[2021-09-01 02:01:17,2021-09-02 12:31:17)',48),
(11,'[2021-08-16 01:30:17,2021-08-16 01:46:17)',37),
(12,'[2021-08-06 09:35:23,2021-08-10 09:19:23)',21),
(13,'[2021-08-17 06:12:21,2021-08-20 04:40:21)',12),
(14,'[2021-08-21 05:45:03,2021-08-23 16:24:03)',38),
(15,'[2021-08-10 01:55:48,2021-08-10 23:23:48)',39),
(16,'[2021-08-28 06:26:59,2021-08-29 21:25:59)',28);
我可以使用以下查询以 60 分钟(或任何值)为间隔生成一系列时间戳,并获取所有重叠的事件(并获取在每个时间戳发生的事件的计数)。效果很好:
SELECT row_number() OVER () AS id,
grid.bin,
count(DISTINCT t.id) AS id_count,
FROM (
SELECT generate_series('2021-08-01 00:00:00'::timestamp,
'2021-08-07 23:59:59'::timestamp, interval '60 min') AS bin
FROM event
) grid
LEFT JOIN event t ON t."order_dates" @> grid.bin
GROUP BY grid.bin
ORDER BY grid.bin;
https://www.db-fiddle.com/f/5P4G7DCY2vdZfLFSi5cA9p/0
我也知道我可以使用此查询生成具有给定间隔的时间戳 范围 而不仅仅是时间戳。
SELECT tsrange((lag(bin) OVER()), bin, '[)')
FROM generate_series(
'2021-08-01 12:00:00'::timestamp,
'2021-08-07 12:00:00',
'60 minute')
AS a OFFSET 1;
https://www.db-fiddle.com/f/nPKTb82SknB3XYi5exrtkz/1
但我似乎无法弄清楚如何组合这两个查询,将第一个查询的 generate_series
部分替换为第二个查询。我知道我需要使用 &&
(重叠)而不是 @>
(包含元素)。
如果您能帮助我们解决这个问题,我们将不胜感激。这可能很简单,但我不确定在解决这样的问题时甚至要搜索什么。
在FROM
子句中使用generate_series
:
SELECT row_number() OVER (ORDER BY lower(grid.bin)) AS id, -- needs ORDER BY
grid.bin,
count(t.id) AS id_count -- no need for DISTINCT
FROM (SELECT tsrange(
lag(t) OVER (ORDER BY t),
t
)
FROM generate_series(
'2021-08-01 00:00:00'::timestamp,
'2021-08-07 23:59:59'::timestamp,
interval '60 min'
) AS times(t)
) AS grid(bin)
LEFT JOIN event t ON t."order_dates" @> grid.bin
GROUP BY grid.bin
ORDER BY lower(grid.bin);
我想在一个时间间隔内生成一系列时间戳范围,并为所有重叠事件查询 table。我 几乎 在那里,但对 SQL 还是很陌生,似乎无法克服这个困难。
为了测试,我构建了一个 table 包含一系列事件,每个事件都发生在一个日期时间范围内:
CREATE TABLE event (id int, order_dates tsrange, flow int);
INSERT INTO event VALUES
(1,'[2021-09-01 10:55:01,2021-09-04 15:16:01)',50),
(2,'[2021-08-15 20:14:27,2021-08-18 22:19:27)',36),
(3,'[2021-08-03 12:51:47,2021-08-05 11:28:47)',41),
(4,'[2021-08-17 09:14:30,2021-08-20 13:57:30)',29),
(5,'[2021-08-02 20:29:07,2021-08-04 19:19:07)',27),
(6,'[2021-08-26 02:01:13,2021-08-26 08:01:13)',39),
(7,'[2021-08-25 23:03:25,2021-08-27 03:22:25)',10),
(8,'[2021-08-12 23:40:24,2021-08-15 08:32:24)',26),
(9,'[2021-08-24 17:19:59,2021-08-29 00:48:59)',5),
(10,'[2021-09-01 02:01:17,2021-09-02 12:31:17)',48),
(11,'[2021-08-16 01:30:17,2021-08-16 01:46:17)',37),
(12,'[2021-08-06 09:35:23,2021-08-10 09:19:23)',21),
(13,'[2021-08-17 06:12:21,2021-08-20 04:40:21)',12),
(14,'[2021-08-21 05:45:03,2021-08-23 16:24:03)',38),
(15,'[2021-08-10 01:55:48,2021-08-10 23:23:48)',39),
(16,'[2021-08-28 06:26:59,2021-08-29 21:25:59)',28);
我可以使用以下查询以 60 分钟(或任何值)为间隔生成一系列时间戳,并获取所有重叠的事件(并获取在每个时间戳发生的事件的计数)。效果很好:
SELECT row_number() OVER () AS id,
grid.bin,
count(DISTINCT t.id) AS id_count,
FROM (
SELECT generate_series('2021-08-01 00:00:00'::timestamp,
'2021-08-07 23:59:59'::timestamp, interval '60 min') AS bin
FROM event
) grid
LEFT JOIN event t ON t."order_dates" @> grid.bin
GROUP BY grid.bin
ORDER BY grid.bin;
https://www.db-fiddle.com/f/5P4G7DCY2vdZfLFSi5cA9p/0
我也知道我可以使用此查询生成具有给定间隔的时间戳 范围 而不仅仅是时间戳。
SELECT tsrange((lag(bin) OVER()), bin, '[)')
FROM generate_series(
'2021-08-01 12:00:00'::timestamp,
'2021-08-07 12:00:00',
'60 minute')
AS a OFFSET 1;
https://www.db-fiddle.com/f/nPKTb82SknB3XYi5exrtkz/1
但我似乎无法弄清楚如何组合这两个查询,将第一个查询的 generate_series
部分替换为第二个查询。我知道我需要使用 &&
(重叠)而不是 @>
(包含元素)。
如果您能帮助我们解决这个问题,我们将不胜感激。这可能很简单,但我不确定在解决这样的问题时甚至要搜索什么。
在FROM
子句中使用generate_series
:
SELECT row_number() OVER (ORDER BY lower(grid.bin)) AS id, -- needs ORDER BY
grid.bin,
count(t.id) AS id_count -- no need for DISTINCT
FROM (SELECT tsrange(
lag(t) OVER (ORDER BY t),
t
)
FROM generate_series(
'2021-08-01 00:00:00'::timestamp,
'2021-08-07 23:59:59'::timestamp,
interval '60 min'
) AS times(t)
) AS grid(bin)
LEFT JOIN event t ON t."order_dates" @> grid.bin
GROUP BY grid.bin
ORDER BY lower(grid.bin);