sea*_*abr 1 postgresql postgresql-9.2
我想计算两个日期之间的范围,就像这个例子:
代理 | 登录_开始 | 登录_END --------+----------------------+---------------- --- 101 | 2016-01-01 06:00:00 | 2016-01-01 06:29:59 102 | 2016-01-01 06:00:00 | 2016-01-01 08:20:00 103 | 2016-01-01 06:00:00 | 2016-01-01 06:01:00 101 | 2016-01-01 10:00:00 | 2016-01-01 10:01:00 101 | 2016-01-01 10:02:00 | 2016-01-01 10:03:00
...并在 30 分钟和代理之间分开几个小时,只是一个例子:
时间 | LOGIN_QTY ---+----------- 06:00 - 06:30 | 3 06:30 - 07:00 | 1 07:00 - 07:30 | 1 07:30 - 08:00 | 1 08:00 - 08:30 | 1 10:00 - 10:30 | 1
问题:代理 102 从 6:00 到 8:20 在线,并且需要计算范围 => 06:00 - 06:30, 06:30 - 07:00, 07:00 - 07:30, 07:30 - 08:00 , 08:00 - 08:30
这是我的 SQL:
WITH min_max_time AS (
SELECT MIN(login_start), MAX(login_end)
FROM agents
), periods(time) AS (
SELECT generate_series(min, max, '30 minutes'::interval)
FROM min_max_time
)
SELECT
time || ' - ' || (time + '30 minutes'::interval),
COUNT(*) FILTER ( WHERE
tsrange(login_start, login_end, '[]') && tsrange(time, time + '30 minutes'::interval, '[]')
)
FROM agents, periods
GROUP BY time
ORDER BY time
;
Run Code Online (Sandbox Code Playgroud)
结果:
?????????????????????????????????????????????????????? ??? ? ?柱子?? 数数 ? ?????????????????????????????????????????????????????? ??? ? 2016-01-01 06:00:00 - 2016-01-01 06:30:00?3 ? ? 2016-01-01 06:30:00 - 2016-01-01 07:00:00 ?1 ? ? 2016-01-01 07:00:00 - 2016-01-01 07:30:00 ?1 ? ? 2016-01-01 07:30:00 - 2016-01-01 08:00:00?1 ? ? 2016-01-01 08:00:00 - 2016-01-01 08:30:00?1 ? ? 2016-01-01 08:30:00 - 2016-01-01 09:00:00 ?0 ? ? 2016-01-01 09:00:00 - 2016-01-01 09:30:00 ?0 ? ? 2016-01-01 09:30:00 - 2016-01-01 10:00:00 ?0 ? ? 2016-01-01 10:00:00 - 2016-01-01 10:30:00 ?1 ? ?????????????????????????????????????????????????????? ???
我需要为 9.4+ 之前的 Postgres 版本重写查询。
唯一的问题似乎是FILTER条款。你可以重写:
COUNT(*) FILTER ( WHERE tsrange(login_start, login_end, '[]')
&& tsrange(time, time + '30 minutes'::interval, '[]')
)
Run Code Online (Sandbox Code Playgroud)
作为:
COUNT(CASE WHEN tsrange(login_start, login_end, '[]')
&& tsrange(time, time + '30 minutes'::interval, '[]')
THEN 1 END
)
Run Code Online (Sandbox Code Playgroud)
我也会使用包含-排除间隔:[). 否则某些行将被计算两次。
| 归档时间: |
|
| 查看次数: |
51 次 |
| 最近记录: |