2014-10-25 5 views
0

У меня есть таблица MCU_RAW с повторяющейся последовательностью переменных, которые меняются. Есть 23 разных переменных.SQL Oracle - Pivot с синхронизацией

SELECT DISTINCT(N_CODE) "Code" 
FROM MCU_RAW 
WHERE N_LOGTYPE = 2 
AND F_VALUE is not NULL 
ORDER BY N_CODE 
--All Rows Fetched: 23 in 17,775 seconds 
--[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] 

Авансовый масштабируется просмотр фактических данных из

SELECT to_char(D_ENTRY, 'YYYY-MM-DD HH24:mi:SS') "DateTime" 
     , N_MS "MS" 
     , N_CODE "Code" 
     , F_VALUE 
FROM mcu_raw 
WHERE N_LOGTYPE = 2 
AND F_VALUE is not null 
AND d_entry < to_Date('2014-10-01 19:04:52', 'YYYY-MM-DD HH24:MI:SS'); 

будет выглядеть

DateTime    MS  Code F_VALUE 
2014-09-05 09:37:52  153  1  1 
2014-09-05 09:37:52  215  2  0 
2014-09-05 09:37:52  246  3  3 
2014-09-05 09:37:52  278  1  1 
2014-09-05 09:37:52  324  2  0 
2014-09-05 09:37:52  340  4  292439 
2014-09-05 09:37:52  402  1  1 
2014-09-05 09:37:52  480  2  0 
2014-09-05 09:37:52  512  5  17,26 
2014-09-05 09:37:52  605  1  1 
2014-09-05 09:37:52  652  2  0 
2014-09-05 09:37:52  683  6  24,96 
2014-09-05 09:37:52  714  1  1 
2014-09-05 09:37:52  777  2  0 
2014-09-05 09:37:52  824  7  110 
2014-09-05 09:37:53  104  1  2 
2014-09-05 09:37:53  136  2  3 
2014-09-05 09:37:53  215  3  4 

То, что я хотел бы сделать, это повернуть данные из MCU_RAW в другой который я создал. Для того, чтобы строка содержала данные времени из первого кода в последовательности, а затем столбец для каждого кода содержит самое последнее значение.

SELECT to_char(D_ENTRY, 'YYYY-MM-DD HH24:mi:SS') "DateTime" 
     , N_MS "MS" 
     , C0001 
     , C0002 
     , C0003 
     , C0004 
     , C0006 
     , C0007 
    FROM MCU 

Желаемая выход из пуха масштабируется предварительного просмотра:

DateTime    MS C0001 C0002 C0003 C0004 C0005 C0006 C0007 
2014-09-05 09:37:52  153  1  0  3 (null) (null) (null) (null) 
2014-09-05 09:37:52  278  1  0  3 292439 (null) (null) (null) 
2014-09-05 09:37:52  402  1  0  3 292439 17,26 (null) (null) 
2014-09-05 09:37:52  605  1  0  3 292439 17,26 24,96 (null) 
2014-09-05 09:37:52  714  1  0  3 292439 17,26 24,96 110 
2014-09-05 09:37:53  104  2  3  4 292439 17,26 24,96 110 

То, что я сделал до сих пор вставляется код 1, чтобы получить правильный выбор времени для каждой строки.

INSERT INTO mcu (D_ENTRY, N_MS, C0001) 
SELECT D_ENTRY, N_MS, F_VALUE 
FROM MCU_raw 
WHERE N_CODE = 1 
AND N_LOGTYPE = 2 
AND F_VALUE is not null 
AND d_entry < to_Date('2014-10-01 19:04:52', 'YYYY-MM-DD HH24:MI:SS') 
ORDER BY D_ENTRY, N_MS; 

Отсюда я продолжаю стучать головой о стену, пытаясь выяснить, как обновить каждую строку с последним значением для каждого столбца.

EDIT: Я решил использовать N_MS из первого вхождения N_CODE = 1 в повторяющейся последовательности.

F_VALUE WHERE N_CODE = 1 is C0001 
F_VALUE WHERE N_CODE = 2 is C0002 
F_VALUE WHERE N_CODE = 3 is C0003 

и т.д ...

+0

Вам нужно объяснить правила игры здесь. Как вы решаете, какие значения N_MS взять? Как вы решаете, следует ли назначать F_VALUE на C0001 или C0007? – APC

ответ

0
with mcu_raw as (
    select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS') datetime, 153 ms, 1 code, 1 f_value from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  215,  2,  0 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  246,  3,  3 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  278,  1,  1 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  324,  2,  0 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  340,  4,  292439 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  402,  1,  1 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  480,  2,  0 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  512,  5,  17.26 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  605,  1,  1 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  652,  2,  0 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  683,  6,  24.96 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  714,  1,  1 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  777,  2,  0 from dual 
    union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),  824,  7,  110 from dual 
    union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),  104,  1,  2 from dual 
    union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),  136,  2,  3 from dual 
    union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),  215,  3,  4 from dual 
), 
mcu_raw_tree as (
    select datetime, ms, code, f_value, 
     case when code_prev > code then null else ms_prev end ms_parent 
    from (select datetime, ms, code, f_value, 
       lag(code) over(order by datetime, ms) code_prev, 
       lag(ms) over(order by datetime, ms) ms_prev 
      from mcu_raw) 
), 
mcu_raw_path as (
    select sys_connect_by_path(code || '_' || f_value, '#') path, 
     connect_by_root datetime datetime, 
     connect_by_root ms ms, 
     connect_by_isleaf lf, connect_by_root code root 
    from mcu_raw_tree 
    start with ms_parent is null 
    connect by prior ms = ms_parent 
), 
mcu_raw_parse as (
    select datetime, ms, path, 
     substr(regexp_substr(path, '1_[^#]+', 1, 1), 3) c0001, 
     substr(regexp_substr(path, '2_[^#]+', 1, 1), 3) c0002, 
     substr(regexp_substr(path, '3_[^#]+', 1, 1), 3) c0003, 
     substr(regexp_substr(path, '4_[^#]+', 1, 1), 3) c0004, 
     substr(regexp_substr(path, '5_[^#]+', 1, 1), 3) c0005, 
     substr(regexp_substr(path, '6_[^#]+', 1, 1), 3) c0006, 
     substr(regexp_substr(path, '7_[^#]+', 1, 1), 3) c0007 
    from mcu_raw_path where lf = 1 and root = 1 
    order by datetime, ms 
) 
select to_char(datetime, 'YYYY-MM-DD HH24:MI:SS'), ms 
    , case when c0001 is null then lag(c0001 ignore nulls) over (order by datetime, ms) else c0001 end c0001 
    , case when c0002 is null then lag(c0002 ignore nulls) over (order by datetime, ms) else c0002 end c0002 
    , case when c0003 is null then lag(c0003 ignore nulls) over (order by datetime, ms) else c0003 end c0003 
    , case when c0004 is null then lag(c0004 ignore nulls) over (order by datetime, ms) else c0004 end c0004 
    , case when c0005 is null then lag(c0005 ignore nulls) over (order by datetime, ms) else c0005 end c0005 
    , case when c0006 is null then lag(c0006 ignore nulls) over (order by datetime, ms) else c0006 end c0006 
    , case when c0007 is null then lag(c0007 ignore nulls) over (order by datetime, ms) else c0007 end c0007 
from mcu_raw_parse; 
  1. сделать дерево (найти родителей для других, то 1-кодов)
  2. Вызов Иерархический запрос построить путь
  3. Разбираем путь соответствующим
  4. Ручка NULLS
  5. Используйте вставку для выбора ...

P.S. Ваш вопрос не на 100% ясен, я построил этот запрос в основном, посмотрев «желаемый результат»