2

特定のテキスト ファイル形式から読み取ったデータの行ごとのダンプを表すテーブルがあります。各行は、コードで示される「マスター」行または「詳細」行を表す場合がありrec_typeます。関連する詳細行と一緒に「マスター」行を取得するクエリを書きたいと思います。私は仕事をするものを思いつきましたが、それは少しハックのようで、もしあればより良い方法に興味があります.

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 用ですが、今年は 11g R1 にアップグレードする必要があります。

4

2 に答える 2

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; 

ご覧のとおり、現在の "200" レコードに関連する "100" レコードを取得するために、セットの先頭から現在の行までのウィンドウで MAX レポート分析関数を使用しています。次に、外側のクエリで、不要な「100」レコードを破棄しています。

emp_name を取得するには、rec_seq をデータに追加して、MAX 関数が引き続き正しいヘッダー レコードを選択できるようにする必要がありました。次に、外側のクエリで rec_seq を切り落とします。

FIRST_VALUE や KEEP 構文など、他の分析関数や構文を試してみましたが、どちらもこの作業を簡単にするものではないようです。問題は、ウィンドウが一定のオフセットではなく、rec_type の値によって定義されることです。

于 2010-01-25T08:04:24.950 に答える
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          

これは、より保守しやすいソリューションに役立つ可能性があり、comm で区切られた EMP_DATA フィールドを個別に解析して検証できるようになります。

ちょっと考えてみてください。Analytics ソリューションのみを探している場合は申し訳ありません。

于 2010-01-25T11:25:46.600 に答える