我需要以下要求的帮助:
我有下表:
id | status | created_at | closed_at
1 'OPEN' '2019-05-08T12:30:24Z' null
2 'CLOSED' '2019-05-08T12:50:22Z' '2019-05-08T13:05:53Z'
3 'CLOSED' '2019-05-08T13:20:00Z' '2019-05-08T13:40:12Z'
4 'CLOSED' '2019-05-08T13:55:47Z' '2019-05-08T14:05:36Z'
5 'OPEN' '2019-05-08T14:15:57Z' null
6 'CLOSED' '2019-05-08T14:30:29Z' '2019-05-08T14:40:00Z'
7 'CLOSED' '2019-05-08T14:55:38Z' '2019-05-08T15:05:51Z'
对于时间范围
created_at='2019-05-08T13:00:00Z'
closed_at ='2019-05-08T15:00:00Z'
输出应为:
timestamp | id
2019-05-08 13:00:00 1,2,3,4
2019-05-08 14:00:00 1,4,5,6,7
请注意,1
在13:00和14:00存在,因为它的created_at从12:30开始,并且没有closed_at(空),因此它在整个时间范围内都“存在”。
我能想到的最接近的是:
SELECT TIMESTAMP WITH TIME ZONE 'epoch' +
INTERVAL '1 second' * round(extract('epoch' from created_at) / 3600) * 3600 as created_at,
id
FROM issues
WHERE (created_at BETWEEN '2019-05-08T13:00:00Z' AND '2019-05-08T15:00:00Z') OR
(closed_at BETWEEN '2019-05-08T13:00:00Z' AND '2019-05-08T15:00:00Z') OR
(status='OPEN')
GROUP BY
created_at,id
ORDER BY created_at;
给出
"2019-05-08 13:00:00+00" "3"
"2019-05-08 13:00:00+00" "2"
"2019-05-08 13:00:00+00" "1"
"2019-05-08 14:00:00+00" "4"
"2019-05-08 14:00:00+00" "5"
"2019-05-08 15:00:00+00" "6"
"2019-05-08 15:00:00+00" "7"
甚至可以通过选择查询来做到吗?
答案 0 :(得分:2)
假设您的意思是created_at ='2019-05-08T13:00:00Z',您应该可以使用tstzranges轻松完成此操作。
WITH time_ranges as
(SELECT tstzrange(t, t + '1 hour'::interval, '[]') as t_range
FROM generate_series('2019-05-08T13:00:00Z'::timestamptz,
'2019-05-08T14:00:00Z'::timestamptz,
'1 hour'::interval) g(t))
,
test_values AS (
SELECT * from (values
(1, '2019-05-08T12:30:24Z'::timestamptz, null::timestamptz),
(2, '2019-05-08T12:50:22Z', '2019-05-08T13:05:53Z'),
(3, '2019-05-08T13:20:00Z', '2019-05-08T13:40:12Z'),
(4, '2019-05-08T13:55:47Z', '2019-05-08T14:05:36Z'),
(5, '2019-05-08T14:15:57Z', null),
(6, '2019-05-08T14:30:29Z', '2019-05-08T14:40:00Z'),
(7, '2019-05-08T14:55:38Z', '2019-05-08T15:05:51Z')
) v(id, created_at, closed_at)
)
select lower(t_range), string_agg(id::text, ',' ORDER BY id)
FROM time_ranges
JOIN test_values on tstzrange(created_at, closed_at, '[]') && t_range
GROUP BY lower(t_range);
lower | string_agg
------------------------+------------
2019-05-08 13:00:00+00 | 1,2,3,4
2019-05-08 14:00:00+00 | 1,4,5,6,7
(2 rows)
唯一棘手的部分是加入从created_at到closed_at的tstzrange与给定小时数之间的重叠。您根本不需要状态栏。