2017-05-04 5 views
3

XMLは以下に添付されています。私が使用しているクエリは、各ポストコードに適用されたアドレス行を返すことです。SQL ServerでネストされたXMLノードを操作する

誤った出力:

Code Reaper PC1 PC1_AL1 PC1_AL2 
Code Reaper PC1 PC2_AL1 PC2_AL2 
Code Reaper PC1 PC3_AL1 PC3_AL2 
... 9 rows in total 

私は以下の予想される出力を得るにはどうすればよいですか?基本的には、私はそれの隣にあるそれぞれのポストコードのアドレス行だけを必要とします。

Code Reaper PC1 PC1_AL1 PC1_AL2 
Code Reaper PC2 PC2_AL1 PC2_AL2 
Code Reaper PC3 PC3_AL1 PC3_AL2 

これは私が試みているものです。あなたのFROM句から

DECLARE @XMLDocument XML 
SET @XMLDocument = N'<People><Person> 
     <PersonDetails> 
      <Surname>Code</Surname> 
      <Forename>Reaper</Forename> 
     </PersonDetails> 
     <HomeInformation> 
      <Address> 
      <PostCode>PC1</PostCode> 
      <AddressLines> 
       <AddressLine1>PC1_AL1</AddressLine1> 
       <AddressLine2>PC1_AL2</AddressLine2> 
      </AddressLines> 
      </Address> 
      <Address> 
      <PostCode>PC2</PostCode> 
      <AddressLines> 
       <AddressLine1>PC2_AL1</AddressLine1> 
       <AddressLine2>PC2_AL2</AddressLine2> 
      </AddressLines> 
      </Address> 
      <Address> 
      <PostCode>PC3</PostCode> 
      <AddressLines> 
       <AddressLine1>PC3_AL1</AddressLine1> 
       <AddressLine2>PC3_AL2</AddressLine2> 
      </AddressLines> 
      </Address> 
     </HomeInformation> 
     </Person> 
    </People> 
    ' 
SELECT 
    [Surname], 
    [GivenName], 
    [PostCode], 
    [AddressLine1], 
    [AddressLine2] 
FROM 
    (SELECT  
     ISNULL(Person.PersonDetails.value('Surname[1]', 'nvarchar(max)'),'') AS [Surname], 
     ISNULL(Person.PersonDetails.value('Forename[1]', 'nvarchar(max)'),'') AS [GivenName],  
     ISNULL(HomeInformation.[Address].value('PostCode[1]', 'nvarchar(max)'),'') AS [PostCode], 
     ISNULL(HomeInformationAddress.AddressLines.value('AddressLine1[1]', 'nvarchar(max)'),'') AS [AddressLine1], 
     ISNULL(HomeInformationAddress.AddressLines.value('AddressLine2[1]', 'nvarchar(max)'),'') AS [AddressLine2] 
    FROM 
     @XMLDocument.nodes('People/Person/PersonDetails') AS Person(PersonDetails) 
    OUTER APPLY 
     PersonDetails.nodes('../HomeInformation/Address') HomeInformation([Address]) 
    OUTER APPLY 
     PersonDetails.nodes('../HomeInformation/Address/AddressLines') HomeInformationAddress(AddressLines)  
    ) as X 

答えて

0

この2行は、クロス参加しているお互いに:

OUTER APPLY PersonDetails.nodes('../HomeInformation/Address') HomeInformation([Address]) 
OUTER APPLY HomeInformation.nodes('../AddressLines') HomeInformationAddress(AddressLines) 

OUTER APPLY PersonDetails.nodes('../HomeInformation/Address') HomeInformation([Address]) 
OUTER APPLY PersonDetails.nodes('../HomeInformation/Address/AddressLines') HomeInformationAddress(AddressLines) 

あなたはこれを防ぐために、最初の1に二つの従属にする必要があり

+1

あなたはこれを試してみましたでしょうか? 2番目の '../'は間違っています。あなたの解決策は正しく返されません...最初の問題は '.nodes()'への最初の呼び出しが深くまで潜ることです...あなたの提案は原則的に正しいですが、この初期の問題は修復されません。より正確に前方にナビゲートする方がいいです... – Shnugo

+0

答えをありがとう。私は最後の行で訂正をしなければならなかった "OUTER APPLY HomeInformation.Address.nodes( 'AddressLines')HomeInformationAddress(AddressLines)'しかし、なぜ私のコードが動作していなかったのかを知る必要があった。 1つは修正です。 – CodeReaper

+0

@ Shnugoはい、あなたは正しいです。残念ながら、私は自分のiPhoneにSQL Serverを持っていないので、いつも私の答えをテストすることはできません。 – RBarryYoung

1

逆方向のナビゲーションは避けてください。 ../の必要はありません。

最初の.nodes()コールは、すべて<Person>のノードが<People>に戻ってくるでしょう。 .nodes()への2回目の呼び出しでは、<Address>ノードが返されます。最後の要素はすべて<AddressLine>の要素を返します。

SELECT  
    ISNULL(prs.value('(PersonDetails/Surname/text())[1]', 'nvarchar(max)'),'') AS [Surname], 
    ISNULL(prs.value('(PersonDetails/Forename/text())[1]', 'nvarchar(max)'),'') AS [GivenName],  
    ISNULL(addr.value('(PostCode/text())[1]', 'nvarchar(max)'),'') AS [PostCode], 
    ISNULL(addrLn.value('(AddressLine1/text())[1]', 'nvarchar(max)'),'') AS [AddressLine1], 
    ISNULL(addrLn.value('(AddressLine2/text())[1]', 'nvarchar(max)'),'') AS [AddressLine2] 
FROM 
    @XMLDocument.nodes('People/Person') AS A(prs) 
OUTER APPLY 
    prs.nodes('HomeInformation/Address') B(addr) 
OUTER APPLY 
    addr.nodes('AddressLines') C(addrLn); 

あなたは見つけるread this answer、なぜ((.../text())[1])シンプル...[1]よりもよりも優れています...

+0

ありがとうございます。間違いなく、私はあなたの答えから拾い上げるいくつかのベストプラクティス – CodeReaper

関連する問題