簡單nodes
和value
功能應該是足夠了:
DECLARE @xml XML = N'<SearchResponse>
<Data>
<Information>
<Code>Code 1</Code>
<Options>
<Option>
<TID>1</TID>
<Rooms>
<ReturnRoom>
<RoomId>1</RoomId>
<Description>Single</Description>
</ReturnRoom>
<ReturnRoom>
<RoomId>2</RoomId>
<Description>Standard</Description>
</ReturnRoom>
</Rooms>
</Option>
<Option>
<TID>2</TID>
<Rooms>
<ReturnRoom>
<RoomId>1</RoomId>
<Description>Single</Description>
</ReturnRoom>
</Rooms>
</Option>
</Options>
</Information>
</Data>
</SearchResponse>';
SELECT b.value('(../../../../Code/text())[1]', 'NVARCHAR(MAX)') AS Code
,b.value('(../../TID/text())[1]', 'NVARCHAR(MAX)') AS TID
,b.value('(./RoomId/text())[1]', 'NVARCHAR(MAX)') AS RoomId
,b.value('(./Description/text())[1]', 'NVARCHAR(MAX)') AS Description
FROM @xml.nodes('/SearchResponse/Data/Information/Options/Option/Rooms/ReturnRoom') AS a(b);
Rextester demo
編輯:
如果你真的需要聚合字符串,你可以使用:
WITH cte AS (
SELECT b.value('(../../../../Code/text())[1]', 'NVARCHAR(MAX)') AS Code
,b.value('(../../TID/text())[1]', 'NVARCHAR(MAX)') AS TID
,b.value('(./RoomId/text())[1]', 'NVARCHAR(MAX)') AS RoomId
,b.value('(./Description/text())[1]', 'NVARCHAR(MAX)') AS Description
FROM @xml.nodes('/SearchResponse/Data/Information/Options/Option/Rooms/ReturnRoom') AS a(b)
)
SELECT Code, TID,
STRING_AGG(RoomId, ';') AS RoomId,
STRING_AGG(Description, ';') AS Description
FROM cte
GROUP BY Code, TID;
這將用於SQL Server 2017+工作。使用較低版本時,您必須使用不同的方法,如XML或CLR功能。
DBFiddle
編輯2:
作爲@Shnugo避免多次向後導航可以通過使用CROSS APPLY
來避免:
WITH cte AS (
SELECT b.value('(../../Code/text())[1]', 'NVARCHAR(MAX)') AS Code
,b.value('(TID/text())[1]', 'NVARCHAR(MAX)') AS TID
,d.value('(RoomId/text())[1]', 'NVARCHAR(MAX)') AS RoomId
,d.value('(Description/text())[1]', 'NVARCHAR(MAX)') AS Description
FROM @xml.nodes('/SearchResponse/Data/Information/Options/Option') AS a(b)
CROSS APPLY a.b.nodes('Rooms/ReturnRoom') AS c(d)
)
SELECT Code, TID, STRING_AGG (RoomId, ';'), STRING_AGG(Description, ';')
FROM cte
GROUP BY Code, TID;
DBFiddle 2
好的答案,+1從我身邊,但我寧願使用'.nodes()'調用'