2016-07-06 57 views
2

我正在使用Microsoft SQL Server。具有多个子元素的SQL查询分层XML

我有一个简单的层次结构像在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 

我怎样才能得到我想要的结果?我应该加入一个内部查询或什么?可能我让它太复杂了,当然有一个简单的解决方案呢?

+0

这是一个很好的问题:Copy'n'pasteable测试代码,自己的努力,预计输出,清晰的解释..如果只有所有的问题都是这样的:-)投了票! – Shnugo

回答

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 
+0

啊,CROSS APPLY,我以前见过它,但是无法将我的头包裹在它的周围......感谢您闪电般的快速反应! –

+0

@LouisSomers,很高兴看到这个!你非常接近! Thx对于你的问题来说,复制你的查询并不是什么大不了的事,输入更多的字母并放置答案......快乐编码! – Shnugo