使用SQL查询层次结构XML,其中包含多个子元素。

3

我正在使用Microsoft SQL Server。

我有一个简单的层次结构,类似于Xml中的有向图:

DECLARE @XML as XML = CAST(
'<ROOT>
    <NODE NODE_ID="1">
        <EDGE>2</EDGE>
        <EDGE>3</EDGE>
        <EDGE>4</EDGE>
    </NODE>
    <NODE NODE_ID="2">
        <EDGE>1</EDGE>
        <EDGE>3</EDGE>
    </NODE>
</ROOT>' AS XML);

我的期望输出是这样的一个表格:

SOURCE_NODE_ID | DEST_NODE_ID
1              | 2
1              | 3
1              | 4
2              | 1
2              | 3

查询类似这样的代码:
SELECT  B.value('data(@NODE_ID)','int') AS SOURCE_NODE_ID,
        A.B.value('(EDGE/text())[1]', 'int') AS DEST_NODE_ID
FROM @XML.nodes('/ROOT/NODE') AS A(B);

仅返回第一个边:

SOURCE_NODE_ID | DEST_NODE_ID
1              | 2
2              | 1

这个表现稍微好一点:

SELECT  B.value('data(@NODE_ID)','int') AS SOURCE_NODE_ID,
        B.query('EDGE').value('.', 'int') AS DEST_NODE_ID
FROM @XML.nodes('/ROOT/NODE') AS A(B);

只有它将所有边缘连接成一个单元格:
SOURCE_NODE_ID | DEST_NODE_ID
1              | 234
2              | 13

我怎样才能得到我想要的结果?我应该使用内部查询或其他方法吗?也许我把它搞得太复杂了,肯定有一个简单的解决方案对吧?


1
这是一个好问题:可复制的测试代码,自己的努力,期望的输出,清晰的解释... 如果所有问题都像这样就好了 :-) 投了赞成票! - Shnugo
1个回答

5

试试这样做

因为有许多NODE元素,所以您需要为它们调用.nodes()。 因为有许多嵌套的EDGE元素,所以您需要为它们调用CROSS APPLY .nodes()

其余部分非常简单...

DECLARE @XML as XML = CAST(
'<ROOT>
    <NODE NODE_ID="1">
        <EDGE>2</EDGE>
        <EDGE>3</EDGE>
        <EDGE>4</EDGE>
    </NODE>
    <NODE NODE_ID="2">
        <EDGE>1</EDGE>
        <EDGE>3</EDGE>
    </NODE>
</ROOT>' AS XML);

SELECT Nd.value('@NODE_ID','INT') AS SOURCE_NODE_ID
      ,Edg.value('.','INT') AS DEST_NODE_ID
FROM @XML.nodes('/ROOT/NODE') AS A(Nd)
CROSS APPLY A.Nd.nodes('EDGE') AS B(Edg)

结果

SOURCE_NODE_ID  DEST_NODE_ID
1               2
1               3
1               4
2               1
2               3

啊,CROSS APPLY,我以前见过,但还不能完全理解它...谢谢你的快速回复! - Louis Somers
@LouisSomers,很高兴看到这个!你非常接近了!多亏了你的好问题,复制你的查询,输入更多字母并放置答案并不是什么大问题...编程愉快! - Shnugo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接