Запрос T-SQL XPath, включая родительский - PullRequest
0 голосов
/ 27 апреля 2018

Эта проблема все время возиться с моим днем ​​в пятницу:

У меня есть этот 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 голосов
/ 27 апреля 2018

Ваш собственный код использует .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 против INNER JOIN)

0 голосов
/ 27 апреля 2018

Предположение: в field.

имеется только один элемент id.
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)

Оператор .. означает «выбрать родителя узла» в XPATH. Таким образом, запрос выберет родителя item, потом родителя items, затем первого дочернего узла id

...