我有一个带有时间戳列的 postgres 表:
开始日期时间 | 结束日期时间 | 持续时间 | id |
---|---|---|---|
2021-10-17 03:13:00 | 2021-10-17 03:15:02 | 302 | 6214550 |
2021-10-17 03:15:02 | 2021-10-17 04:17:03 | 4,021 | 6214551 |
我需要将其分成限制在分钟结束或
end_datetime
的桶中,如下:
开始日期时间 | 结束日期时间 | id |
---|---|---|
2021-10-17 03:13:00 | 2021-10-17 03:14:00 | 6214550 |
2021-10-17 03:14:00 | 2021-10-17 03:15:00 | 6214550 |
2021-10-17 03:15:00 | 2021-10-17 03:15:02 | 6214550 |
2021-10-17 03:15:02 | 2021-10-17 03:16:00 | 6214551 |
2021-10-17 03:16:00 | 2021-10-17 03:17:00 | 6214551 |
2021-10-17 03:17:00 | 2021-10-17 03:17:03 | 6214551 |
架构(PostgreSQL v15)
CREATE TABLE t (
"start_datetime" TIMESTAMP,
"end_datetime" TIMESTAMP,
"duration" INT,
"id" INTEGER
);
INSERT INTO t
("start_datetime", "end_datetime", "duration", "id")
VALUES
('2021-10-17 03:13:00', '2021-10-17 03:15:02', '302', '6214550'),
('2021-10-17 03:15:02', '2021-10-17 04:17:03', '4021', '6214551');
查询#1
SELECT id
-- Since we truncated down to the minute in the generate_series, we need to handle the first datetime differently,
-- choosing it over any datetime before it
, CASE WHEN start_datetime > m THEN start_datetime ELSE m END AS start_datetime
-- We find the next minute (ie end_datetime) using LEAD(), except for the last row (per id) as it doesn't exist.
-- When that's the case, we use end_datetime
, COALESCE(LEAD(m) OVER(PARTITION BY id ORDER BY m), t.end_datetime) AS end_datetime
FROM t, generate_series(date_trunc('minute', start_datetime), end_datetime, '1 minute'::interval) AS f(m)
ORDER BY id, m;
id | 开始日期时间 | 结束日期时间 |
---|---|---|
6214550 | 2021-10-17T03:13:00.000Z | 2021-10-17T03:14:00.000Z |
6214550 | 2021-10-17T03:14:00.000Z | 2021-10-17T03:15:00.000Z |
6214550 | 2021-10-17T03:15:00.000Z | 2021-10-17T03:15:02.000Z |
6214551 | 2021-10-17T03:15:02.000Z | 2021-10-17T03:16:00.000Z |
6214551 | 2021-10-17T03:16:00.000Z | 2021-10-17T03:17:00.000Z |
... | 被截断 | |
6214551 | 2021-10-17T04:16:00.000Z | 2021-10-17T04:17:00.000Z |
6214551 | 2021-10-17T04:17:00.000Z | 2021-10-17T04:17:03.000Z |