假设我有下表CALLS
,该表按类型CALL
的列TIMESTAMP
排序:
CALL TYPE
--------------------- ------
31.10.2018 10:00:00 OFF
31.10.2018 11:00:00 ON
31.10.2018 12:00:00 ON
31.10.2018 13:00:00 ON
31.10.2018 14:00:00 OFF
31.10.2018 15:00:00 OFF
31.10.2018 16:00:00 ON
31.10.2018 17:00:00 ON
我想编写一个视图,以查找带有TYPE=ON
的各个呼叫组并提取其开始和结束日期。结果,对于给定的示例,我得到了两个组:
START END
--------------------- ---------------------
31.10.2018 11:00:00 31.10.2018 13:00:00
31.10.2018 16:00:00 31.10.2018 17:00:00
我们应该假设:
ON
行用OFF
行分隔,但第一行和最后一行不必是OFF
类型是否可以在Oracle 12c中实现?
答案 0 :(得分:2)
这是一个孤岛问题。在这种情况下,行号与聚合的不同将满足您的要求:
select min(call) as start_time, max(call) as end_time
from (select t.*,
row_number() over (partition by type order by call) as seqnum_t,
row_number() over (order by call) as seqnum
from t
) t
where type = 'ON'
group by (seqnum - seqnum_t)
答案 1 :(得分:1)
如果运行Oracle 12,则还可以使用SQL for Pattern Matching
会是这样的:
WITH t (CALL, TYPE) AS (
SELECT TO_TIMESTAMP('31.10.2018 10:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'OFF' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 11:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'ON' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 12:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'ON' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 13:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'ON' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 14:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'OFF' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 15:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'OFF' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 16:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'ON' FROM dual UNION ALL
SELECT TO_TIMESTAMP('31.10.2018 17:00:00', 'dd.mm.yyyy hh24:mi:ss'), 'ON' FROM dual)
SELECT *
FROM t
MATCH_RECOGNIZE (
ORDER BY CALL
MEASURES
FINAL MIN(CALL) AS CALL_START,
FINAL MAX(CALL) AS CALL_END
PATTERN ( CALL_ON+ )
DEFINE
CALL_ON AS TYPE = 'ON'
);
+-----------------------------------------------------------+
| CALL_START | CALL_END |
+-----------------------------------------------------------+
| 31.10.2018 11:00:00.000 | 31.10.2018 13:00:00.000 |
| 31.10.2018 16:00:00.000 | 31.10.2018 17:00:00.000 |
+-----------------------------------------------------------+