需要帮助在oracle XML列中编写循环查询

时间:2018-02-01 04:59:36

标签: oracle

我将以下XML数据放在一列中:

<Employee_part part_id="A" part_name="ABC" >    

  <Employee_scoring_information >
    <keyset keyset_weight="1" number_of_keyset_members="1">
      <integer_key value="2"/>
    </keyset>
  </Employee_scoring_information>
</Employee_part>
<Employee_part part_id="B" part_name="BCD" >

  <Employee_scoring_information >
    <match_keyset keyset_weight="1" number_of_keyset_members="3">
    <integer_key value="2"/>
      <source_key correct_target_id="4" source_key_id="1"/>
      <source_key correct_target_id="1" source_key_id="2"/>
      <source_key correct_target_id="2" source_key_id="3"/>
    </match_keyset>
    <match_keyset keyset_weight="1" number_of_keyset_members="3">
      <source_key correct_target_id="5" source_key_id="1"/>
      <source_key correct_target_id="1" source_key_id="2"/>
      <source_key correct_target_id="2" source_key_id="3"/>
    </match_keyset>

  </Employee_scoring_information>
</Employee_part>
<Employee_part part_id="C" part_name="CDE" >

  <Employee_scoring_information >
    <keyset keyset_weight="1" number_of_keyset_members="2">
      <integer_key value="1"/>
      <integer_key value="2"/>
    </keyset>
  </Employee_scoring_information>
</Employee_part>

XML有三个部分(Employee_part part_id =&#34; A&#34;,&#34; B&#34;,&#34; C&#34;)A部分有键集,B部分有 match_keyset ,部分c有键集。当它有键集时,我需要从integer_key / @ Value(Ex:2)中提取数据,当它有match_keyset时,我需要从source_key correct_target_id,source_key_id中提取数据,格式为(例如:1 / 4,2 / 1, 3/2; 1 / 5,2 / 1,3 / 2;)。每个部分都由Pipe(|)符号分隔。

我正在尝试编写以下查询以显示以下输出: 2 | 1 / 4,2 / 1,3 / 2; 1 / 5,2 / 1,3 / 2; | 1,2

SELECT CASE EXISTSNODE (EMP_CNTNT_XML,
                        '/Employee/Employee_content/Employee_part')
          WHEN 1
          THEN
             RTRIM (
                REPLACE (
                   REPLACE (
                      CAST (
                         XMLQUERY (
                            '
for $i in //Employee_part/@part_id return 
concat
( 
concat
(
xs:string
(
for $x in //Employee_part where $x/@part_id = $i return 
for $y in $x//integer_key/@value return 
concat
(
xs:string($y)
,","
)
)
,


xs:string
(
for $k in //Employee_part where $k/@part_id = $i return  
concat(                                 
xs:string(
for $x in $k/@source_key_id return 
for $y in $k/@correct_target_id return                                       
concat(xs:string($x), "/", xs:string($y), "" ) )
,",")                     

)

)
,
"|"
) 
'
                            PASSING EMP_CNTNT_XML RETURNING CONTENT) AS VARCHAR2 (1000)),
                      ' ',
                      ''),
                   ',|',
                   '|'),
                '|')
       END
          AS XML_DATA
  FROM Employee
 WHERE emp_no = 'SCH1234';

1 个答案:

答案 0 :(得分:0)

我的建议是将XML更改为关系数据,如下所示:

CREATE TABLE emp AS
SELECT XMLTYPE('<Employee><Employee_content>
<Employee_part part_id="A" part_name="ABC" >    

  <Employee_scoring_information >
    <keyset keyset_weight="1" number_of_keyset_members="1">
      <integer_key value="2"/>
    </keyset>
  </Employee_scoring_information>
</Employee_part>
<Employee_part part_id="B" part_name="BCD" >

  <Employee_scoring_information >
    <match_keyset keyset_weight="1" number_of_keyset_members="3">
    <integer_key value="2"/>
      <source_key correct_target_id="4" source_key_id="1"/>
      <source_key correct_target_id="1" source_key_id="2"/>
      <source_key correct_target_id="2" source_key_id="3"/>
    </match_keyset>
    <match_keyset keyset_weight="1" number_of_keyset_members="3">
      <source_key correct_target_id="5" source_key_id="1"/>
      <source_key correct_target_id="1" source_key_id="2"/>
      <source_key correct_target_id="2" source_key_id="3"/>
    </match_keyset>

  </Employee_scoring_information>
</Employee_part>
<Employee_part part_id="C" part_name="CDE" >

  <Employee_scoring_information >
    <keyset keyset_weight="1" number_of_keyset_members="2">
      <integer_key value="1"/>
      <integer_key value="2"/>
    </keyset>
  </Employee_scoring_information>
</Employee_part>
</Employee_content></Employee>') AS Employee_part
FROM dual;

CREATE OR REPLACE VIEW EMP_SCORING_INFORMATION AS 
SELECT part_id, part_name, SCORING_INFORMATION
FROM EMP e
    CROSS JOIN XMLTABLE('/Employee/Employee_content/Employee_part' PASSING EMPLOYEE_PART COLUMNS
        part_id VARCHAR2(10) PATH '@part_id',
        part_name VARCHAR2(10) PATH '@part_name',
        SCORING_INFORMATION XMLTYPE PATH 'Employee_scoring_information'
        ) p;

CREATE OR REPLACE VIEW EMP_MATCH_KEYSET AS 
SELECT part_id, part_name, keyset_weight, number_of_keyset_members, keyset_NO, keyset
FROM EMP_SCORING_INFORMATION e
    CROSS JOIN XMLTABLE('/Employee_scoring_information/match_keyset' PASSING SCORING_INFORMATION COLUMNS
        keyset_weight INTEGER PATH '@keyset_weight',
        number_of_keyset_members INTEGER PATH '@number_of_keyset_members',
        keyset_NO FOR ORDINALITY,
        keyset XMLTYPE PATH '/'
    ) p;

CREATE OR REPLACE VIEW EMP_KEYSET AS 
SELECT part_id, part_name, keyset_weight, number_of_keyset_members, keyset_NO, keyset
FROM EMP_SCORING_INFORMATION e
    CROSS JOIN XMLTABLE('/Employee_scoring_information/keyset' PASSING SCORING_INFORMATION COLUMNS
        keyset_weight INTEGER PATH '@keyset_weight',
        number_of_keyset_members INTEGER PATH '@number_of_keyset_members',
        keyset_NO FOR ORDINALITY,
        keyset XMLTYPE PATH '/'
    ) p;    

CREATE OR REPLACE VIEW EMP_MATCH_KEYSET_source_key AS 
SELECT keyset_NO, part_id, part_name, keyset_weight, number_of_keyset_members,
    key_NO, correct_target_id, source_key_id
FROM EMP_MATCH_KEYSET e
    CROSS JOIN XMLTABLE('/match_keyset/source_key' PASSING keyset COLUMNS
        correct_target_id INTEGER PATH '@correct_target_id',
        source_key_id INTEGER PATH '@source_key_id',
        key_NO FOR ORDINALITY
    )p;

CREATE OR REPLACE VIEW EMP_MATCH_KEYSET_INTEGER_KEY AS 
SELECT keyset_NO, part_id, part_name, keyset_weight, number_of_keyset_members,
    key_NO, integer_key
FROM EMP_MATCH_KEYSET e
    CROSS JOIN XMLTABLE('/match_keyset/integer_key' PASSING keyset COLUMNS
        integer_key INTEGER PATH '@value',
        key_NO FOR ORDINALITY
    )p;

CREATE OR REPLACE VIEW EMP_KEYSET_INTEGER_KEY AS 
SELECT keyset_NO, part_id, part_name, keyset_weight, number_of_keyset_members,
    key_NO, integer_key
FROM EMP_KEYSET e
    CROSS JOIN XMLTABLE('/keyset/integer_key' PASSING keyset COLUMNS
        integer_key INTEGER PATH '@value',
        key_NO FOR ORDINALITY
    )p;

我不完全了解您的要求,但作为起点,您可以使用此查询:

WITH t AS
    (SELECT LISTAGG(SOURCE_KEY_ID||'/'||CORRECT_TARGET_ID, ',') WITHIN GROUP (ORDER BY key_NO) AS KEY_ID, keyset_NO
    FROM EMP_MATCH_KEYSET_SOURCE_KEY
    GROUP BY keyset_NO)
SELECT LISTAGG(KEY_ID, '; ') WITHIN GROUP (ORDER BY keyset_NO)
FROM t;

1/4,2/1,3/2; 1/5,2/1,3/2

使用相当简单的JOIN,UNION和/或CASE,您应该能够获得所需的输出。