包含Parent的T-SQL XPath查询

时间:2018-04-27 14:44:25

标签: sql-server xml tsql xpath xquery

这个问题一直在我周五下午搞乱:

我有这个XML:

declare @xml as XML
set @xml =
'<fields>
  <field>
    <id>1</id>
    <items>
      <item>
        <name>name1_1</name>
        <value>value1_1</value>
      </item>
      <item>
        <name>name1_2</name>
        <value>value1_2</value>
      </item>
    </items>
  </field>
  <field>
    <id>2</id>
    <items>
      <item>
        <name>name2_1</name>
        <value>value2_1</value>
      </item>
      <item>
        <name>name2_2</name>
        <value>value2_2</value>
      </item>
    </items>
  </field>
</fields>'

使用T-SQL和XPath,我需要一个查询来获得这个结果:

id   name     value
1    name1_1  value1_1
1    name1_2  value1_2
2    name2_1  value2_1
2    name2_2  value2_2

我的名字和价值在于:

SELECT c.value('name[1]', 'nvarchar(255)') name,
       c.value('value[1]', 'nvarchar(255)') value
FROM @xml.nodes('fields/field/items/item') t(c)

...但是如何插入父列“id”?

2 个答案:

答案 0 :(得分:0)

假设:每id只有一个field元素。

SELECT c.value('../../id[1]', 'int') id,
       c.value('name[1]', 'nvarchar(255)') name,
       c.value('value[1]', 'nvarchar(255)') value
FROM @xml.nodes('fields/field/items/item') t(c)

..运算符表示&#34;选择节点的父节点&#34;在XPATH中。因此,查询将选择item的父级,然后选择items的父级,然后选择第一个子级节点id

答案 1 :(得分:0)

您自己的代码使用.nodes()从重复元素中获取派生表。在您的情况下,有两个级别的重复元素:

  • 许多字段和每个字段
  • 很多项目

您必须使用.nodes()两次:

SELECT fld.value(N'(id/text())[1]',N'int') AS FieldID
      ,itm.value(N'(name/text())[1]',N'nvarchar(max)') AS ItemName
      ,itm.value(N'(value/text())[1]',N'nvarchar(max)') AS ItemValue
FROM @xml.nodes(N'/fields/field') AS A(fld)
OUTER APPLY A.fld.nodes(N'items/item') AS B(itm);

第一个.nodes()返回XML片段,每个字段一个,为每个字段片段调用第二个节点来选择它们的项目。

当您不希望看到没有OUTER APPLY个节点的字段时,如果可能有没有<item>个节点的字段和CROSS APPLY,请使用<item>(类似于LEFT JOIN vs INNER JOIN