1

如何最好地修改以下语句,以便我收到带有 Address.Location 的 Contact.Name 列表(如果可能,我想使用 XPath 而不是子查询/WHERE 条件)?我在@@@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;'))

当针对提供的 XML 文档评估此 XPath 表达式时:

<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 / XPath 2.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 回答