2010-01-25 2 views
2

У меня есть таблица, которая представляет собой построчный дамп данных, считываемых из определенного формата текстового файла. Каждая строка может представлять собой «ведущую» или «детальную» строку, обозначенную кодом rec_type. Я хотел бы написать запрос, который получает «ведущие» строки рядом со связанными строками. Я придумал что-то, что делает эту работу, но это кажется немного хакерским, и я заинтересован в лучших способах, если они есть.Окно аналитической функции Oracle, определяемое данными

CREATE TABLE mdtest 
(rec_seq NUMBER  PRIMARY KEY 
,rec_type VARCHAR2(3) NOT NULL 
,rec_data VARCHAR2(100) NOT NULL); 

INSERT INTO mdtest VALUES (1, '100', 'Bill Jones'); 
INSERT INTO mdtest VALUES (2, '200', '20080115,100.25'); 
INSERT INTO mdtest VALUES (3, '100', 'John Smith'); 
INSERT INTO mdtest VALUES (4, '200', '20090701,80.95'); 
INSERT INTO mdtest VALUES (5, '200', '20091231,110.35'); 

желаемого результат:

SEQ_EMP EMP_NAME SEQ_DATA EMP_DATA 
======= ========== ======== =============== 
     1 Bill Jones   2 20080115,100.25 
     3 John Smith   4 20090701,80.95 
     3 John Smith   5 20091231,110.35 

Предположение:

  • запись обрабатывается в последовательности rec_seq
  • первого типа записи является "100"
  • каждого "100" запись имеет 1 или более "200 "записей

Примечание: это для Oracle 9i, однако в этом году мы должны обновить до 11 г R1.

+0

+1 Хорошие данные образца. –

ответ

2

Вот что я до сих пор:

SELECT seq_emp 
     ,SUBSTR(emp_seq_name,10) emp_name 
     ,seq_data 
     ,emp_data 
FROM (SELECT MAX(CASE WHEN rec_type = '100' THEN rec_seq END) 
       OVER (ORDER BY rec_seq 
        ROWS BETWEEN UNBOUNDED PRECEDING 
          AND CURRENT ROW) seq_emp 
      ,MAX(CASE 
        WHEN rec_type = '100' 
        THEN TO_CHAR(rec_seq,'fm00000000') || '|' || rec_data 
        END) 
       OVER (ORDER BY rec_seq 
        ROWS BETWEEN UNBOUNDED PRECEDING 
          AND CURRENT ROW) emp_seq_name 
      ,rec_seq seq_data 
      ,rec_type 
      ,rec_data emp_data 
     FROM mdtest) 
WHERE rec_type = '200' 
ORDER BY seq_data; 

Как вы можете видеть, я использую MAX отчетов аналитической функции с окном, начиная с верхней части высаживать в текущей строке, чтобы получить соответствующая запись «100» для текущей записи «200»; то во внешнем запросе я отбрасываю ненужные записи «100».

Чтобы получить emp_name, мне пришлось добавить rec_seq с данными, чтобы функция MAX по-прежнему выбирала правильную запись заголовка; то во внешнем запросе я отключу rec_seq.

Я играл с другими аналитическими функциями и синтаксисом, включая FIRST_VALUE и синтаксис KEEP, но ни один из них, похоже, не упрощает эту задачу; сложность заключается в том, что окно определяется значением rec_type вместо некоторого постоянного смещения.

+1

@Jeffrey: вы делаете один проход данных, вы не сможете запросить его более эффективно. Как вы, вероятно, знаете, что модель «хакерская» (мастер и детализация в одной таблице), и, следовательно, все запросы на такой модели будут выглядеть странно :) –

1

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

create table mdtest100 as select * from mdtest where rec_type = 100; 

create table mdtest200 as select * from mdtest where rec_type = 200; 

with mdtest_detail as 
    (
    select 
     (select max(m.rec_seq) from mdtest100 m 
     where m.rec_seq < r200.rec_seq) master_rec_seq, 
     r200.* 
    from 
     mdtest200 r200 
    ) 
select 
    m.rec_seq seq_emp, 
    m.rec_data emp_name, 
    d.rec_seq seq_data, 
    d.rec_data emp_data 
from 
    mdtest_detail d 
     inner join mdtest100 m on m.rec_seq = d.master_rec_seq 
order by 
    seq_emp, 
    seq_data; 


    SEQ_EMP EMP_NAME SEQ_DATA EMP_DATA   
    1  Bill Jones 2   20080115,100.25   
    3  John Smith 4   20090701,80.95   
    3  John Smith 5   20091231,110.35   

Это может поддается более обслуживаемым решением и позволит вам разобрать и проверить поле EMP_DATA Comm-отделенный отдельно.

Просто подумайте - извините, если вы ищете решение Google Analytics.

+0

это нормально - возможно, хорошая идея указать, что таблица не предназначена для этот вид запроса; это всего лишь журнал активности импорта. –