1

次のステートメントを変更して、Address.Locationを含むContact.Nameのリストを受け取るにはどうすればよいですか(可能な場合はサブクエリ/ WHERE条件ではなくXPathを使用したい)。@@@ Nameであらゆる種類の構文を試しましたが、うまくいきませんでした:(-元のノードを参照したいと思います。

DECLARE @data AS XML
SELECT @data = '
    <Data>
        <Contact Name="John"/>
        <Contact Name="Bob"/>
        <Address ContactName="John" Location="JohnStreet1"/>
        <Address ContactName="John" Location="JohnStreet2"/>
        <Address ContactName="Bob" Location="BobStreet1"/>
    </Data> 
'

SELECT 
    x.v.value('@Name','VARCHAR(255)') [Contact.Name],   
    y.v.value('@Location','VARCHAR(255)') [Address.Location]
FROM 
    @data.nodes('/Data[1]/Contact') AS x(v)
CROSS APPLY
    x.v.nodes('/Data[1]/Address[@ContactName=@@@Name]') AS y(v)
ORDER BY
    x.v.value('@Name','VARCHAR(255)')

PS。パラメータはリテラルである必要があるため、これは機能しません:(

x.v.nodes('/Data[1]/Address[@ContactName=' + x.v.value('@Name','VARCHAR(255)') + ']') AS y(v)

注意:現在、目的の結果セットを取得するために次のことを行っています(ただし、クリーンなXPathの方法ではありません)。

SELECT 
    x.v.value('@Name','VARCHAR(255)') [Contact.Name],   
    y.v.value('@Location','VARCHAR(255)') [Address.Location]
FROM 
    @data.nodes('/Data[1]/Contact') AS x(v)
CROSS APPLY
    x.v.nodes('/Data[1]/Address') AS y(v)
WHERE
    y.v.value('@ContactName','VARCHAR(255)')=x.v.value('@Name','VARCHAR(255)')
ORDER BY
    x.v.value('@Name','VARCHAR(255)')
4

2 に答える 2

2

これが純粋なXQueryです(これはたまたま純粋なXPath 2.0式でもあります):

  for $c in /*/Contact/@Name
    return
      for $loc in /*/Address[@ContactName eq $c]/@Location
           return
              data(($c, $loc, '&#xA;'))

このXPath式が提供されたXMLドキュメントに対して評価される場合:

<Data>
    <Contact Name="John"/>
    <Contact Name="Bob"/>
    <Address ContactName="John" Location="JohnStreet1"/>
    <Address ContactName="John" Location="JohnStreet2"/>
    <Address ContactName="Bob" Location="BobStreet1"/>
</Data>

必要な正しい結果が生成されます:

John JohnStreet1
 John JohnStreet2 
 Bob BobStreet1 

これは純粋なXQuery/XPath2.0ソリューションです。SQL Server XQuery方言がわかりません。このソリューションを、ケースに適用できることを願っています。

おそらく次のようなものです:

select @data.query(
      'for $c in /*/Contact/@Name
        return
          for $loc in /*/Address[@ContactName eq $c]/@Location
               return
                  data(($c, $loc, "&#xA;"))'
                   )

更新

Mikael Erikssonのコメントに記載されているように、SQL Server XQueryは「異種シーケンス」を受け入れず、エラーを発生させます。

次に、これは、わずかに変更されたクエリが機能します

select @data.query(
      'for $c in /*/Contact/@Name
        return
          for $loc in /*/Address[@ContactName eq $c]/@Location
               return
                  (string($c), string($loc), "&#xA;")'

上記の必要な正しい結果を生成します

于 2012-10-03T13:04:59.667 に答える
0

これはあなたが求めていることをしますか?

;with cte as
(
    SELECT  
        x.v.value('@Name','VARCHAR(255)') ContactName,
        @data xmlData
    FROM  
        @data.nodes('/Data[1]/Contact') AS x(v)
)
select 
    ContactName as [Contact.Name], 
    y.v.value('@Location','VARCHAR(255)') as [Address.Location] 
from
    cte
        cross apply
    xmlData.nodes('/Data[1]/Address[@ContactName=sql:column("ContactName")]') AS y(v) 
order by 
    ContactName
于 2012-09-27T15:25:23.543 に答える