2010-03-22 1 views
1

У меня есть таблица в базе данных Oracle, в которой, помимо прочего, есть столбец DATE, который загружается меткой времени вставки каждой строки , Мне нужно использовать существующие данные в такой таблице для анализа корреляции между некоторыми событиями, так что данные, как это:Используйте аналитические функции для группировки набора записей, когда метки времени в строках меньше или равны значению

COL_1   COL_2   TS 
    A    1   Mon 15, February 2010 10:03:22 
    B    2   Mon 15, February 2010 10:05:37 
    C    3   Mon 15, February 2010 10:20:21 
    D    4   Mon 15, February 2010 10:20:21 
    E    5   Mon 15, February 2010 10:20:24 
    F    6   Mon 15, February 2010 10:23:35 
    G    7   Mon 15, February 2010 10:45:22 

Я хотел бы соотнести с чем-то вроде этого, assumming связанных записей находятся между 5-ем максимальная разница между текущим и следующим «TS»:

FIRST_TS       COUNT 
Mon 15, February 2010 10:03:22   2 
Mon 15, February 2010 10:20:21   4 
Mon 15, February 2010 10:45:22   1 

Возможно ли использовать аналитические функции для достижения этого? Как?

+0

Какая версия Oracle? Должно быть 9i или более позднее использовать аналитику. –

ответ

1

Это будет группироваться строки, которые менее чем за 5 минут, удаленных от предыдущего ряда:

--ALTER SESSION SET nls_date_format= 'dy dd, month yyyy hh24:mi:ss'; 
--ALTER SESSION SET nls_date_language='ENGLISH'; 
SQL> WITH DATA AS (
    2 SELECT to_date('Mon 15, February 2010 10:03:22') ts FROM dual 
    3 UNION ALL SELECT to_date('Mon 15, February 2010 10:05:37') FROM dual 
    4 UNION ALL SELECT to_date('Mon 15, February 2010 10:20:21') FROM dual 
    5 UNION ALL SELECT to_date('Mon 15, February 2010 10:20:21') FROM dual 
    6 UNION ALL SELECT to_date('Mon 15, February 2010 10:20:24') FROM dual 
    7 UNION ALL SELECT to_date('Mon 15, February 2010 10:23:35') FROM dual 
    8 UNION ALL SELECT to_date('Mon 15, February 2010 10:45:22') FROM dual 
    9 ) 
10 SELECT MIN(ts) first_ts, COUNT(*) COUNT 
11 FROM (SELECT ts, SUM(gap) over(ORDER BY ts) ts_group 
12    FROM (SELECT ts, 
13       CASE 
14        WHEN ts - lag(ts) over(ORDER BY ts) 
15         <= 5/(60 * 24) THEN 
16        0 
17        ELSE 
18        1 
19       END gap 
20      FROM DATA)) 
21 GROUP BY ts_group; 

FIRST_TS        COUNT 
-------------------------------- ---------- 
mon 15, february 2010 10:03:22   2 
mon 15, february 2010 10:20:21   4 
mon 15, february 2010 10:45:22   1 
+0

Отлично! Большое спасибо! –

0

Я не думаю, что вам нужна аналитика для этого вам просто нужно сгенерировать пять-минутные интервалы. Следующий код использует выражение Common Table Expression (факторинг подзапроса AKA) для генерации пятиминутных интервалов с заданной даты начала. Основной запрос использует SUM() и случай(), чтобы произвести подсчет записей, которые попадают в интервал

Вот тестовые данные:

SQL> select * from t23 
    2/

C  COL2 COL3 
- ---------- ----------------- 
A   1 15-feb-2010 10:03 
B   2 15-feb-2010 10:05 
C   3 15-feb-2010 10:20 
D   4 15-feb-2010 10:20 
E   5 15-feb-2010 10:20 
F   6 15-feb-2010 10:23 
G   7 15-feb-2010 10:45 

7 rows selected. 

SQL> 

И вот это результат

SQL> with t_range as (
    2  select to_date('15 February 2010 10:00','DD Month YYYY hh24:mi') 
    3            + ((level-1)/288) as this_5mins 
    4    , to_date('15 February 2010 10:00','DD Month YYYY hh24:mi') 
    5            + (level/288) as next_5mins 
    6  from dual 
    7  connect by level <= 12 
    8  ) 
    9 select t_range.this_5mins 
10   , sum(case when t23.col3 >= t_range.this_5mins 
11     and t23.col3 < t_range.next_5mins 
12     then 1 
13     else 0 end) as cnt 
14 from t23 cross join t_range 
15 group by t_range.this_5mins 
16/

THIS_5MINS    CNT 
----------------- ---------- 
15-feb-2010 10:10   0 
15-feb-2010 10:20   4 
15-feb-2010 10:30   0 
15-feb-2010 10:05   1 
15-feb-2010 10:55   0 
15-feb-2010 10:15   0 
15-feb-2010 10:40   0 
15-feb-2010 10:45   1 
15-feb-2010 10:00   1 
15-feb-2010 10:35   0 
15-feb-2010 10:25   0 
15-feb-2010 10:50   0 

12 rows selected. 

SQL> 
0

Вот версия с аналитическими функциями. Просто замените таблицу для подзапроса union, где я создаю таблицу с вашими данными:

select distinct 
    first_value(ts) over (partition by continuous_group order by ts) first_ts 
    , count(ts) over (partition by continuous_group) count 
from (
    select col_1, col_2, ts, sum(discontinuity) over (order by ts) continuous_group 
    from (
    select col_1, col_2, ts, case when lag(ts) over (order by ts) + numtodsinterval(5,'MINUTE') <= ts then 1 else 0 end discontinuity 
    from (
    select 'A' col_1, 1 col_2, to_date('2010-2-15 10:03:22', 'YYYY-MM-DD HH24:MI:SS') ts from dual 
    union (
    select 'B' col_1, 2 col_2, to_date('2010-2-15 10:05:37', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
    union (
    select 'C' col_1, 3 col_2, to_date('2010-2-15 10:20:21', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
    union (
    select 'D' col_1, 4 col_2, to_date('2010-2-15 10:20:21', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
    union (
    select 'E' col_1, 5 col_2, to_date('2010-2-15 10:20:24', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
    union (
    select 'F' col_1, 6 col_2, to_date('2010-2-15 10:23:35', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
    union (
    select 'G' col_1, 7 col_2, to_date('2010-2-15 10:45:22', 'YYYY-MM-DD HH24:MI:SS') ts from dual) 
)) 
) order by first_value(ts) over (partition by continuous_group order by ts); 

 Смежные вопросы

  • Нет связанных вопросов^_^