【问题标题】:Find periods from timestamps in ordered table从有序表中的时间戳中查找周期
【发布时间】:2018-11-01 15:08:18
【问题描述】:

假设我有下表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 中实现?

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    这是一个孤岛问题。在这种情况下,行号与聚合的差异可以满足您的要求:

    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)
    

    【讨论】:

      【解决方案2】:

      如果您运行 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     |
      +-----------------------------------------------------------+
      

      【讨论】:

        猜你喜欢
        • 2021-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多