具有多个子元素的

时间:2016-07-06 12:14:45

标签: sql sql-server xml tsql xpath

我正在使用Microsoft SQL服务器。

我有一个简单的层次结构,如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 个答案:

答案 0 :(得分:4)

尝试这样

由于有许多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