在 Oracle 中查找重复的子节点

Posted

技术标签:

【中文标题】在 Oracle 中查找重复的子节点【英文标题】:Find duplicate child nodes in Oracle 【发布时间】:2019-10-18 20:50:54 【问题描述】:

我在 oracle 数据库中有一个存储 XML 数据的列。

由于某种原因,我的查询在插入时未检查现有节点,因此导致在几行中出现重复节点。

我无法找到找到这些重复项的有效方法。

我的 XML 看起来像:

<myroot>
  <mydata>

    <myusers>
      <username>amy</username>
      <userrole/>
      <userrole>junior artist</userrole>
    </myusers>

    <myusers>
      <username>rosy</username>
      <userrole/>
      <userrole>junior artist</userrole>
    </myusers>

    <myusers>
      <username>timmy</username>
      <userrole>junior artist</userrole>
    </myusers>

  </mydata>
</myroot>

如上面的 XML 示例所示,空节点在几行的几个标签中处于空闲状态,但有什么方法可以找到哪些行包含重复项?

过去我使用以下查询仅提取此数据,但不知道如何提取两个数据:

SELECT MYID, EXTRACT(MYDATA, 'myroot/mydata/myusers/userole/text()') 
FROM MYTABLE 
WHERE
EXISTNODE(MYDATA, 'myroot/mydata/myusers/userole') = 1

仅作为背景,我的其他数据提取查询未发送以下错误是现在需要修复上述数据的原因:

ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence

【问题讨论】:

是的,更正了错字。用户角色重复。 【参考方案1】:

考虑使用“XMLTABLE”代替其他现已弃用的“EXTRACT”函数。

如果您将 XML 放在一个表中,我将在下面的示例中将其称为“tbl”,您可以这样做:

with tbl as
(
    select
        XMLType(
        '<myroot>
          <mydata>

            <myusers>
              <username>amy</username>
              <userrole/>
              <userrole>junior artist</userrole>
            </myusers>

            <myusers>
              <username>rosy</username>
              <userrole/>
              <userrole>junior artist</userrole>
            </myusers>

            <myusers>
              <username>timmy</username>
              <userrole>junior artist</userrole>
            </myusers>

          </mydata>
        </myroot>'
        ) xmldata
    from
        dual
)
select username, userrole
from (
    select username, userrole, count(*) over ( partition by username) rolecnt
    from   tbl,
           xmltable('/myroot/mydata/myusers/userrole' 
                          PASSING tbl.xmldata 
                          COLUMNS username VARCHAR2(80) PATH './../username', 
                                  userrole VARCHAR2(80) PATH '.')
    )
where rolecnt > 1
+----------+---------------+
| USERNAME |   USERROLE    |
+----------+---------------+
| amy      |               |
| amy      | junior artist |
| rosy     |               |
| rosy     | junior artist |
+----------+---------------+

注意我假设您输入数据中的“userole”是一个错字,而您的意思是“userrole”。

【讨论】:

我喜欢您的解决方案,它在示例中运行良好,但是当我在数据库值上运行时,用户名从未显示任何值。它总是一片空白。所以我找到了另一种适用于我的数据集的方法。【参考方案2】:

最终对我有用的是找出“myusers”标签和“userrole”的计数。计数不匹配的地方是需要注意的行。我有 2000 行,其中两个有重复,所以这个解决方案对我来说很好。但如果是一组不同的数据,我认为@Matthew McPeak 的解决方案会很好用。

我确信可能有更好、更有效的方法来做到这一点,但以下是对我来说效果很好的一次性查询。

SELECT * FROM 
    (
    select count(*) MYCON, MYID
        from MYTABLE  sa
        cross join xmltable('myroot/mydata/myusers'
            passing sa.MYDATA columns myusers varchar2(1) path '@dummy'
    ) 
    GROUP BY MYID ) BB
JOIN
    (
    select count(*) YOURCON, MYID
        from MYTABLE sa
        cross join xmltable('myroot/mydata/myusers/userrole'
            passing sa.MYDATA columns myusers varchar2(1) path '@dummy'
    ) 
    GROUP BY MYID ) AA
ON  AA.MYID = BB.MYID
WHERE MYCON <> YOURCON

【讨论】:

以上是关于在 Oracle 中查找重复的子节点的主要内容,如果未能解决你的问题,请参考以下文章

高手帮忙:sql 里怎样递归判断父节点和子节

ztree获取当前选中节点子节点id集合的方法(转载)

树(二叉树的插入删除查找遍历)

如何使用 XQuery 获取 XML 文件中的子节点数

iOS7 SpriteKit 如何对两个或多个精灵节点子节点的动画进行分组?

Javascript - ExtJs - TreePanel组件