2017-04-11 12 views
0

私はWITH句でテーブルにいくつかのXMLを解析しようとしていますが、メインクエリではそのテーブルを自身に結合します。しかし、最小限のテストケースでも、記録はありません。ここでOracle:XMLTableの出力を自己結合

は、サンプルxmlです:ここでは

<xml> 
    <entry timestamp="20170330100429" effective="20170329"> 
    <field name="Name"> 
     <ov> <![CDATA[Fran]]> </ov> 
     <nv> <![CDATA[Frank]]> </nv> 
    </field> 
    <field name="Zip"> 
     <ov> <![CDATA[13583]]> </ov> 
     <nv> <![CDATA[13853]]> </nv> 
    </field> 
    </entry> 
    <entry timestamp="20170401094783" effective="20170331"> 
    <field name="MI"> 
     <ov> <![CDATA[J]]> </ov> 
     <nv> <![CDATA[A]]> </nv> 
    </field> 
    <field name="Suffix"> 
     <ov> <![CDATA[Jr]]> </ov> 
     <nv> <![CDATA[III]]> </nv> 
    </field> 
    </entry> 
</xml> 

は、WITH句でテーブルにXMLを平らにするために削ぎ落としたSQLです:

with myxml as 
(
    select 1 xml_id, 
     '<xml> <entry timestamp="20170330100429" effective="20170329"> <field name="Name"> <ov><![CDATA[Fran]]></ov> <nv><![CDATA[Frank]]></nv> </field> <field name="Zip"> <ov><![CDATA[13583]]></ov> <nv><![CDATA[13853]]></nv> </field> </entry> <entry timestamp="20170401094783" effective="20170331"> <field name="MI"> <ov><![CDATA[J]]></ov> <nv><![CDATA[A]]></nv> </field> <field name="Suffix"> <ov><![CDATA[Jr]]></ov> <nv><![CDATA[III]]></nv> </field> </entry> </xml>' x from dual 
), 
HRH as 
(
SELECT au.xml_id, 
     ts.tran_ts as chg_timestr, 
     to_date(substr(ts.tran_ts, 0, 8), 'yyyymmdd') chg_date, 
     cast(substr(ts.tran_ts, 9, 6) as int) chg_time, 
     f.fieldname, 
     f.ov old_value, 
     f.nv new_value 
    FROM myxml au, 
    xmltable('/xml' 
       PASSING XMLTYPE(au.x) 
       COLUMNS entrynode XMLTYPE PATH 'entry' 
    ) as x1, 
    xmltable('/entry' 
       PASSING x1.entrynode 
       COLUMNS tran_ts VARCHAR(16) PATH '@timestamp', 
         fieldnode XMLTYPE  PATH 'field' 
    ) as ts, 
    xmltable('/field' 
       PASSING ts.fieldnode 
       COLUMNS fieldname VARCHAR(250) PATH '@name', 
         nv VARCHAR(250) PATH 'nv', 
         ov VARCHAR(250) PATH 'ov' 
    ) as f 
) 
select * from HRH 

このクエリは、次のような出力が得られます。

XML_ID CHG_TIMESTR CHG_DATE CHG_TIME FIELDNAME OLD_VALUE NEW_VALUE 
====== ============== ========== ======== ========= ========= ========= 
    1 20170330100429 2017-03-30 100429 Name  Fran  Frank  
    1 20170330100429 2017-03-30 100429 Zip  13583  13853  
    1 20170401094783 2017-04-01 94783 MI  J   A   
    1 20170401094783 2017-04-01 94783 Suffix Jr  III  
====== ============== ========== ======== ========= ========= ========= 

代わりに、次のいずれかを使用します。

select * from HRH h1, HRH h2 
select * from HRH h1 join HRH h2 on 1=1 

私は、エラーメッセージが出ます:

Line Pos Text 
==== === ================================================ 
17 23 ORA-19032: Expected XML tag , got no content 
ORA-06512: at "SYS.XMLTYPE", line 310 
ORA-06512: at line 1 
==== === ================================================ 

は、どのように私はこの仕事を得ることができますか?私の全体的な目標は、私のデータセットのxml_idフィールドの組み合わせに対する最新の更新を取得することです。

答えて

0

なぜその動作が見られているのかよく分かりません。最初のCTEを具体化するとエラーは停止しますが、データが見つかりません。

直接関係ありませんが、あなたは、単一のXMLTableコールに、少なくともデータのためのあなたが示されてきた、あなたのクエリを簡素化することができます:

SELECT au.xml_id, 
     x.tran_ts as chg_timestr, 
     to_date(substr(x.tran_ts, 0, 8), 'yyyymmdd') chg_date, 
     cast(substr(x.tran_ts, 9, 6) as int) chg_time, 
     x.fieldname, 
     x.ov old_value, 
     x.nv new_value 
FROM myxml au 
CROSS JOIN xmltable('/xml/entry/field' 
    PASSING XMLTYPE(au.x) 
    COLUMNS tran_ts VARCHAR2(16) PATH './../@timestamp', 
      fieldname VARCHAR2(250) PATH '@name', 
      nv VARCHAR2(250) PATH 'nv', 
      ov VARCHAR2(250) PATH 'ov' 
) x; 

    XML_ID CHG_TIMESTR  CHG_DATE  CHG_TIME FIELDNAME OLD_VALUE NEW_VALUE 
---------- ---------------- ---------- ---------- ---------- ---------- ---------- 
     1 20170330100429 2017-03-30  100429 Name  Fran  Frank  
     1 20170330100429 2017-03-30  100429 Zip  13583  13853  
     1 20170401094783 2017-04-01  94783 MI   J   A   
     1 20170401094783 2017-04-01  94783 Suffix  Jr   III  

しようとしていることがデータを取得しますが、ヌルたくさんの自己結合。また奇妙な。

しかし、たとえあなたの本当のクエリは(あなたはすべての後に、それをストリップダウンと言った)ことを行うにはあまりにも複雑である場合、あなたは目的はあなたが行うことができます最新の更新を取得された

with myxml as 
(
    select /*+ materialize */ 1 xml_id, 
     '<xml> <entry timestamp="20170330100429" effective="20170329"> <field name="Name"> <ov><![CDATA[Fran]]></ov> <nv><![CDATA[Frank]]></nv> </field> <field name="Zip"> <ov><![CDATA[13583]]></ov> <nv><![CDATA[13853]]></nv> </field> </entry> <entry timestamp="20170401094783" effective="20170331"> <field name="MI"> <ov><![CDATA[J]]></ov> <nv><![CDATA[A]]></nv> </field> <field name="Suffix"> <ov><![CDATA[Jr]]></ov> <nv><![CDATA[III]]></nv> </field> </entry> </xml>' x from dual 
), 
HRH as 
(
    SELECT au.xml_id, 
     x.tran_ts as chg_timestr, 
     to_date(substr(x.tran_ts, 0, 8), 'yyyymmdd') chg_date, 
     cast(substr(x.tran_ts, 9, 6) as int) chg_time, 
     x.fieldname, 
     x.ov old_value, 
     x.nv new_value, 
     rank() over (partition by au.xml_id, x.fieldname 
      order by x.tran_ts desc) rnk 
    FROM myxml au 
    CROSS JOIN xmltable('/xml/entry/field' 
    PASSING XMLTYPE(au.x) 
    COLUMNS tran_ts VARCHAR2(16) PATH './../@timestamp', 
      fieldname VARCHAR2(250) PATH '@name', 
      nv VARCHAR2(250) PATH 'nv', 
      ov VARCHAR2(250) PATH 'ov' 
) x 
) 
select * from HRH 
where rnk = 1; 

各ID /フィールドごとに1つのデータセットがあるだけで、サンプルと同じ結果が得られますが、倍数がある場合はそれぞれ最新のものが必要です。また、rank()dense_rank()の解析関数の違いを見て、データが可能であれば、関連があるかどうかを判断してください。

+0

私の質問では何が問題なのか分かりませんが、両方のクエリが機能し、自己結合を実行することもできますが、2番目のクエリを実行してそれが必要です。 – FranPeruzzi