【问题标题】:Oracle XMLQuery- Display comma separated list with two XML nodesOracle XMLQuery - 显示带有两个 XML 节点的逗号分隔列表
【发布时间】:2018-12-28 11:47:47
【问题描述】:

我有一个这样的查询-

WITH xtbl AS (SELECT xmltype ('<root>
                    <parent>
                        <item>
                            <item_detail>AAA</item_detail>
                            <item_amount>1000</item_amount>
                        </item>
                        <item>
                            <item_detail>BBB</item_detail>
                            <item_amount>2000</item_amount>
                        </item>
                    </parent>
                </root>') AS xcol FROM dual)
SELECT xmlcast (
           xmlquery ('root/parent/string-join[item/item_detail/text()]' PASSING xcol RETURNING CONTENT) AS VARCHAR2 (2000))
           AS item_details
  FROM xtbl;

虽然上面指定的示例包含一个节点,但在我的实际问题中,并不是每个&lt;parent&gt; 节点都将包含一个&lt;item&gt; 节点。因此,我无法使用this 答案中描述的 XMLTable 解决方案。

SELECT xmlcast(... 查询是我迄今为止尝试过的,但它不起作用。我的预期输出是这个-

ITEM_DETAILS
------------------
AAA 1000, BBB 2000

请建议我如何修改我的 XMLQuery。

【问题讨论】:

    标签: oracle xpath oracle11g oracle-xml-db


    【解决方案1】:

    您仍然可以使用 XMLTable 调用:

    SELECT x.*
    FROM xtbl
    CROSS JOIN xmltable('/root/parent/item'
           PASSING xcol
           COLUMNS item_detail VARCHAR2(10) path 'item_detail',
                   item_amount NUMBER path 'item_amount'
    ) x;
    
    ITEM_DETAI ITEM_AMOUNT
    ---------- -----------
    AAA               1000
    BBB               2000
    

    然后连接和聚合:

    SELECT listagg(x.item_detail ||' '|| x.item_amount, ', ')
      WITHIN GROUP (ORDER BY item_num) AS item_details
    FROM xtbl
    CROSS JOIN xmltable('/root/parent/item'
           PASSING xcol
           COLUMNS item_detail VARCHAR2(10) path 'item_detail',
                   item_amount NUMBER path 'item_amount',
                   item_num FOR ORDINALITY
    ) x;
    
    ITEM_DETAILS                                      
    --------------------------------------------------
    AAA 1000, BBB 2000
    

    对于没有只会返回 null 的项目的父级。

    不过,您也可以通过 XMLQuery 调用来实现:

    SELECT xmlquery(
      'let $d :=
         for $i in /root/parent/item
           return concat($i/item_detail, " ", $i/item_amount)
       return string-join($d, ", ")'
      PASSING xcol
      RETURNING CONTENT
    ) AS item_details
    FROM xtbl;
    
    ITEM_DETAILS                                      
    --------------------------------------------------
    AAA 1000, BBB 2000
    

    再次与没有仅返回 null 的项目的父项一起使用。

    let $d := 部分使用concat() 连接每个项目的详细信息和金额,它们之间有一个空格。然后使用string-join() 聚合生成的所有$d 值。

    这会返回一个 XMLType,因此要将结果作为纯字符串获取,您可以在问题中使用 XMLCast,或者更简单地使用 .getStringVal()

    SELECT xmlquery(
      ...
    ).getStringVal() AS item_details
    FROM xtbl;
    

    【讨论】:

      【解决方案2】:
      WITH xtbl AS (SELECT xmltype ('<root>
                          <parent>
                              <item>
                                  <item_detail>AAA</item_detail>
                                  <item_amount>1000</item_amount>
                              </item>
                              <item>
                                  <item_detail>BBB</item_detail>
                                  <item_amount>2000</item_amount>
                              </item>
                          </parent>
                      </root>') AS xcol FROM dual)
      SELECT xmlcast (
                 xmlquery (
                 'string-join(/root/parent/item/string-join((*), " "), ", ")' 
                 PASSING xcol
                 RETURNING CONTENT) AS VARCHAR2 (2000)
             )
             AS item_details
        FROM xtbl;
      

      编辑: * 没有什么特别之处。这是child::*的简写

      内部字符串连接: /root/parent/item/string-join(child::*, " ") 连接/root/parent/item 的每个子元素的值(这里指的是&lt;item_detail&gt;&lt;item_amount&gt;。分隔符是space

      就其本身而言,外部字符串连接将每个内部字符串连接的结果与comma 的限制器连接起来。

      EDIT-2:

      'string-join(/root/parent/item/string-join(
                                                 (item_detail, item_amount)
                                                 , " "
                                                )
                   , ", "
                  )' 
      

      【讨论】:

      • 请解释你的答案。 string-join((*)...中的*有什么意义?
      • 已更新。请查看编辑。尝试更改每个 string-join() 的分隔符并进行测试。
      • 是否可以限定节点而不是仅使用*?它是怎么做的?
      猜你喜欢
      • 1970-01-01
      • 2011-01-26
      • 2012-10-29
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      • 2017-02-22
      相关资源
      最近更新 更多