從XML

2017-07-26 36 views
1

的SQL Server中選擇值我有這樣的XML:從XML

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

如何,我可以得到

Code  Name  TID RoomId Description 
--------------------------------------------------- 
Code 1 Hotel 1 1 1;2  Single;Standard 
Code 1 Hotel 1 2 1  Single 

回答

4

簡單nodesvalue功能應該是足夠了:

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

好的答案,+1從我身邊,但我寧願使用'.nodes()'調用'