问题描述
我有一张类似于
的表Start time | End Time | User |
09/02/2021 03:01:13 | 09/02/2021 03:45:15 | ABC |
09/02/2021 03:15:20 | 09/02/2021 05:03:20 | XYZ |
09/02/2021 06:03:12 | 09/02/2021 06:15:30 | DEF |
预期输出:
StDt | EndDt | Count(1)
09/02/2021 00:00:00 | 09/02/2021 01:00:00 | 0
09/02/2021 01:00:00 | 09/02/2021 02:00:00 | 0
09/02/2021 02:00:00 | 09/02/2021 03:00:00 | 0
09/02/2021 03:00:00 | 09/02/2021 04:00:00 | 2
09/02/2021 04:00:00 | 09/02/2021 05:00:00 | 1
09/02/2021 05:00:00 | 09/02/2021 06:00:00 | 0
09/02/2021 06:00:00 | 09/02/2021 07:00:00 | 1
此示例中的间隔是每小时,但我希望将其灵活设置为 10 分钟/15 分钟/30 分钟。 我希望这用单个 sql 编写。 到目前为止,我只能解决如何生成范围。
select t1.StartDt,t1.EndDt from
(
select
(to_char(timestamp '2021-02-09 00:00:00' + numtodsinterval(rownum*60,'MINUTE') - numtodsinterval(60,'MINUTE'),'DD-MM-YYYY hh24:mi')) as StartDt,(to_char(timestamp '2021-02-09 00:00:00' + numtodsinterval(rownum*60,'DD-MM-YYYY hh24:mi')) as EndDt
from dual connect by level <= 24
) t1;
解决方法
你有一个很好的启动,除了在子查询中保留时间值的时间戳格式,并在结果显示阶段将 TO_CHAR
格式移动到主查询以及使用相关子查询和明显计数聚合重叠区间,并使用绑定变量作为时间部分值的占位符(60
,30
,15
),例如
SQL> var min number
SQL> exec :min := 60
PL/SQL procedure successfully completed
min
---------
60
SQL> SELECT TO_CHAR(t.StartDt,'DD-MM-YYYY HH24:MI') AS StartDt,2 TO_CHAR(t.EndDt,'DD-MM-YYYY HH24:MI') AS EndDt,3 ( SELECT COUNT(DISTINCT "User")
FROM tab
WHERE t.EndDt >= Start_Time
AND t.StartDt <= End_Time ) AS Count
4 FROM
5 (
6 SELECT timestamp '2021-02-09 00:00:00' +
7 numtodsinterval(rownum * :min,'MINUTE') -
8 numtodsinterval(:min,'MINUTE') AS StartDt,9 timestamp '2021-02-09 00:00:00' +
10 numtodsinterval(rownum * :min,'MINUTE') AS EndDt
11 FROM dual
12 CONNECT BY level <= 24
13 ) t
14 ORDER BY StartDt;
STARTDT ENDDT COUNT
---------------- ---------------- ----------
09-02-2021 00:00 09-02-2021 01:00 0
09-02-2021 01:00 09-02-2021 02:00 0
09-02-2021 02:00 09-02-2021 03:00 0
09-02-2021 03:00 09-02-2021 04:00 2
09-02-2021 04:00 09-02-2021 05:00 1
09-02-2021 05:00 09-02-2021 06:00 1
09-02-2021 06:00 09-02-2021 07:00 1
09-02-2021 07:00 09-02-2021 08:00 0
.....
.....