在有序表中查找时间戳记中的时间段

时间:2018-10-31 22:12:05

标签: sql oracle plsql

假设我有下表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  

我们应该假设:

  • 组的最小计数为1,因此我们可以获得具有相同开始日期和结束日期的组
  • ON行用OFF行分隔,但第一行和最后一行不必是OFF类型

是否可以在Oracle 12c中实现?

2 个答案:

答案 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     |
+-----------------------------------------------------------+