【问题标题】:Convert rows values into columns - oracle 11g将行值转换为列 - oracle 11g
【发布时间】:2020-01-30 03:46:40
【问题描述】:

我正在从 XML 类型的字段中提取一些数据,从特定标签中获取一些值,并且我设法以这样的结果形式收集它们:

echo  | type| color             | active
-------------------------------------------
echo1 | car | yellow,green,blue | no,no,no
echo1 | car | yellow,green      | yes,yes
echo2 | car | green,blue,red    | no,no,no
echo2 | car | blue,red          | yes,yes
echo3 | car | yellow,green      | no,yes
...

现在我需要将这些结果转换为:

echo  | type| color  | active
------------------------------
echo1 | car | yellow | no
echo1 | car | green  | no
echo1 | car | blue   | no
echo1 | car | yellow | yes
echo1 | car | green  | yes
echo2 | car | green  | no
echo2 | car | blue   | no
echo2 | car | red    | no
echo2 | car | blue   | yes
echo2 | car | red    | yes
echo3 | car | yellow | no
echo3 | car | green  | yes
...

意思是,我需要同时拆分第 3 列和第 4 列的值。 color 列中的每个值在活动列中都有一个对应的值,我需要匹配记录中的这些对。

所以有这样的结果我用这个:

SELECT  echo, type, trim(x.COLUMN_VALUE) color, trim(y.COLUMN_VALUE) active 
FROM 
( RESULTS )
, xmltable(('"' || REPLACE(color, ',', '","') || '"')) x, xmltable(('"' || REPLACE(active, ',', '","') || '"')) y

ORDER BY echo, type, color, active

如果我一次只转换这两列中的一列,它可以正常工作,但是当我想一次转换 2 时,它会将记录相乘,就像将 y 列的值乘以 x 列的值一样。

如果在最后一列中只有“yes”或只有“no”值,那么在选择中使用 distinct 会起作用,它会消除过时(不是真的)记录。但在混合价值观的情况下,我正在努力做到这一点。

谁能给我一个提示如何修复它以不让过时的记录?

提前致谢!


示例 XML:

<rowCollection>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">yellow</column>
  </row>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">green</column>
  </row>
</rowCollection>

用于生成结果的查询片段:

xmlcast(
  xmlquery(
    'string-join(/rowCollection/row/column[5]/text(),",")'
    passing xml_field
    RETURNING CONTENT
  ) AS VARCHAR2(500)
) color,
xmlcast(
  xmlquery(
    'string-join(/rowCollection/row/column[1]/text(),",")'
    passing xml_field
    RETURNING CONTENT
  ) AS VARCHAR2(300)
) active

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    使用递归子查询分解子句并使用INSTR 迭代查找分隔符,然后使用SUBSTR 提取值:

    Oracle 设置

    CREATE TABLE results ( echo, type, color, active ) AS
    SELECT 'echo1', 'car', 'yellow,green,blue', 'no,no,no' FROM DUAL UNION ALL
    SELECT 'echo1', 'car', 'yellow,green',      'yes,yes'  FROM DUAL UNION ALL
    SELECT 'echo2', 'car', 'green,blue,red',    'no,no,no' FROM DUAL UNION ALL
    SELECT 'echo2', 'car', 'blue,red',          'yes,yes'  FROM DUAL UNION ALL
    SELECT 'echo3', 'car', 'yellow,green',      'no,yes'   FROM DUAL;
    

    查询

    WITH lines ( echo, type, rn, idx, color, active, c_start, c_end, a_start, a_end ) AS (
      SELECT echo,
             type,
             ROW_NUMBER() OVER ( ORDER BY echo, type, color, active ),
             1,
             color,
             active,
             1,
             INSTR(color,',',1),
             1,
             INSTR(active,',',1)
      FROM   results
    UNION ALL
      SELECT echo,
             type,
             rn,
             idx + 1,
             color,
             active,
             c_end + 1,
             INSTR(color,',',c_end + 1),
             a_end + 1,
             INSTR(active,',',a_end + 1)
      FROM   lines
      WHERE  c_end > 0
      AND    a_end > 0
    )
    SELECT echo,
           type,
           CASE c_end
           WHEN 0
           THEN SUBSTR( color, c_start )
           ELSE SUBSTR( color, c_start, c_end - c_start )
           END AS color,
           CASE a_end
           WHEN 0
           THEN SUBSTR( active, a_start )
           ELSE SUBSTR( active, a_start, a_end - a_start )
           END AS active
    FROM   lines
    ORDER BY rn, idx
    

    输出

    回声 |类型 |颜色 |积极的 :---- | :--- | :----- | :----- 回声1 |汽车 |黄色 |是的 回声1 |汽车 |绿色 |是的 回声1 |汽车 |黄色 |不 回声1 |汽车 |绿色 |不 回声1 |汽车 |蓝色 |不 回声2 |汽车 |蓝色 |是的 回声2 |汽车 |红色 |是的 回声2 |汽车 |绿色 |不 回声2 |汽车 |蓝色 |不 回声2 |汽车 |红色 |不 回声3 |汽车 |黄色 |不 回声3 |汽车 |绿色 |是的

    db小提琴here


    更新

    不要聚合然后拆分分隔的字符串;只需从 XML 中提取值:

    CREATE TABLE table_name ( xml_field ) AS
    SELECT XMLTYPE( '<rowCollection>
      <row>
        <column name="active">YES</column>
        <column name="customertype">Default</column>
        <column name="type">Default</column>
        <column name="risklevel">Default</column>
        <column name="color">yellow</column>
      </row>
      <row>
        <column name="active">YES</column>
        <column name="customertype">Default</column>
        <column name="type">Default</column>
        <column name="risklevel">Default</column>
        <column name="color">green</column>
      </row>
    </rowCollection>' ) FROM DUAL;
    

    查询

    SELECT x.*
    FROM   table_name t
           CROSS JOIN
           XMLTABLE(
             '/rowCollection/row'
             PASSING t.xml_field
             COLUMNS
               active VARCHAR2(3) PATH '/row/column[@name="active"]',
               type   VARCHAR2(10) PATH '/row/column[@name="type"]',
               color  VARCHAR2(10) PATH '/row/column[@name="color"]'
           ) x;
    

    输出

    会有一种方法来生成echo 列;只是这不包含在您的示例数据中。

    活跃 |类型 |颜色 :----- | :-------- | :----- 是 |默认 |黄色 是 |默认 |绿色

    db小提琴here

    【讨论】:

    • 谢谢!当然适用于我的数据。我添加了一部分 xml,从中提取我的结果。如果您愿意,可以建议另一种提取标签值的方法。
    • 我没有说清楚,但结果实际上是从几个连接的列中收集的,我将它组合到 (echo, type, xml),所以 echo 和 type 列不属于xml 内容。
    • 然后从您加入的表中输出echotype 列,然后从XML 中提取其他值。
    • 是的,现在一切正常。我只是想不出提取 XML 值的语法。谢谢!
    【解决方案2】:

    您可以使用hierarchy查询如下:

    SQL> SELECT ECHO, TYPE,
      2      REGEXP_SUBSTR(COLOR, '[^,]+', 1, COLUMN_VALUE) AS COLOR,
      3      REGEXP_SUBSTR(ACTIVE, '[^,]+', 1, COLUMN_VALUE) AS ACTIVE
      4  FROM RESULTS
      5      CROSS JOIN TABLE ( CAST(MULTISET(
      6          SELECT LEVEL FROM DUAL
      7          CONNECT BY LEVEL <= REGEXP_COUNT(COLOR, ',') + 1
      8      ) AS SYS.ODCINUMBERLIST) );
    
    ECHO  TYP COLOR      ACTIVE
    ----- --- ---------- --------------------------------
    echo1 car yellow     no
    echo1 car green      no
    echo1 car blue       no
    echo1 car yellow     yes
    echo1 car green      yes
    echo2 car green      no
    echo2 car blue       no
    echo2 car red        no
    echo2 car blue       yes
    echo2 car red        yes
    echo3 car yellow     no
    echo3 car green      yes
    
    12 rows selected.
    
    SQL>
    

    干杯!!

    【讨论】:

    • 谢谢!它当然适用于我的数据,非常优雅。只是基数和成本比上面MT0的解决方案要高很多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多