sql - 带有 XMLTABLE 的 Xpath

标签 sql oracle xpath oracle12c

使用此 XML:

<attrs>
    <attr multiple="true" name="LETTER">
        <string>A</string>
        <string>B</string>
        <string>C</string>
        <string>D</string>
    </attr>
    <attr multiple="true" name="NUMBER">
        <string>1</string>
        <string>2</string>
        <string>3</string>
        <string>4</string>
    </attr>
    ...
</attrs>

我正在尝试使用 XMLTABLE 获得此结果:

+------+--------+--------+
| REF  | LETTER | NUMBER |
+------+--------+--------+
| REF1 | A      |      1 |
| REF1 | B      |      2 |
| REF1 | C      |      3 |
| ...  | ...    |    ... |
+------+--------+--------+

我对 Xpath 很不好,我被困在这里,但这连接了所有值:

XMLTABLE('/attrs'
    PASSING XMLTYPE(XML)
    COLUMNS LETTER VARCHAR2(50) PATH 'attr[@name="LETTER"]',
            NUMBER VARCHAR2(50) PATH 'attr[@name="NUMBER"]'
) X

谢谢。

最佳答案

这里是更简单情况的解决方案,需要固定数量的 string 元素。

第一步获取表格中转置形式的数据

create table tab as 
with doc as (
select 
xmltype(q'{<attrs>
    <attr multiple="true" name="LETTER">
        <string>A</string>
        <string>B</string>
        <string>C</string>
        <string>D</string>
    </attr>
    <attr multiple="true" name="NUMBER">
        <string>1</string>
        <string>2</string>
        <string>3</string>
        <string>4</string>
    </attr>
    ...
</attrs>}') as doc from  DUAL)
select x.* from doc,
         XMLTable(
          'for $i in /attrs/attr    
           return $i'
          passing  (doc.doc)
          columns
                 col_name varchar2(10) path '//attr/@name',
                 s1 varchar2(10) path '//string[1]',
                 s2 varchar2(10) path '//string[2]',
                 s3 varchar2(10) path '//string[3]',
                 s4 varchar2(10) path '//string[4]'
                  ) x
;

COL_NAME   S1         S2         S3         S4        
---------- ---------- ---------- ---------- ----------
LETTER     A          B          C          D         
NUMBER     1          2          3          4   

这几乎是您所期望的,但必须进行转置。我确信有一个简单的方法,但这个查询有效。应用 UNPIVOT 而非 PIVOT,然后重命名列。

with q1 as ( 
select * from tab 
UNPIVOT (
     x 
    FOR src 
    IN (
        s1 AS 'X', 
        s2 AS 'Y',
        s3 as 'Z',
        s4 as 'U'
    )
)),
q2 as (
select * from q1
PIVOT (max(x) "VAL"  for (col_name) in 
('LETTER' as "LETTER",
'NUMBER' as "NUMBER")
))
select LETTER_VAL as "LETTER", NUMBER_VAL as "NUMBER"
from q2
order by 1;

UNPIVOT结果

COL_NAME   S X         
---------- - ----------
LETTER     X A         
LETTER     Y B         
LETTER     Z C         
LETTER     U D         
NUMBER     X 1         
NUMBER     Y 2         
NUMBER     Z 3         
NUMBER     U 4

PIVOT结果

S LETTER_VAL NUMBER_VAL
- ---------- ----------
X A          1         
Y B          2         
Z C          3         
U D          4  

最终结果

LETTER     NUMBER    
---------- ----------
A          1         
B          2         
C          3         
D          4 

关于sql - 带有 XMLTABLE 的 Xpath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58978622/

相关文章:

python - selenium可以在outlook online中find_element_by_xpath吗?

php - 如何使用PHP向MySQL添加数据

php - 如何通过 MySQL 查询或 PHP 代码删除无法识别的字符?

asp.net - Oracle 10 和 Oracle 11 客户端共存

java - 有没有办法为 Java 文档提供用于 XPath 查询的 XML 模式

php - 在 xpath 中根据类和样式排除标签

sql - 使用来自返回 JSON 数组的 Postgres 子查询的值

mysql - 建议的 SQL 格式

sql - oracle sql如何做异步查询

java - 如何使用 hibernate 注释验证负值?