Найти периоды по временным меткам в упорядоченной таблице - PullRequest
0 голосов
/ 01 ноября 2018

Предположим, у меня есть следующая таблица 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 type

Можно ли добиться этого в Oracle 12c?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Если вы используете Oracle 12, то вы также можете использовать SQL для сопоставления с образцом

Было бы так:

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     |
+-----------------------------------------------------------+
0 голосов
/ 01 ноября 2018

Это проблема пробелов и островков. В этом случае разница номеров строк с агрегацией делает то, что вы хотите:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...