Столбец XML — трехуровневая иерархия — с перекрестным применением

Мой предыдущий вопрос был решен много">здесь. Теперь я добавляю к нему еще один уровень сложности — данные, которые являются вложенными родителем, дочерним элементом, внуком.

You can see and run sample here: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=df2766c95383d4c8c2d1f55539634341< /а>

Пример кода, где Leg1 может быть поездкой туда, а Leg2 может быть поездкой назад. Каждая нога может иметь один или несколько полетов.

DECLARE @xml XML='
<Reservation>
  <Name>Neal</Name>
    <Leg seq=''1''>
      <Flight>12</Flight>
    </Leg>
    <Leg seq=''2''>
      <Flight>34</Flight>
      <Flight>56</Flight>
    </Leg>
</Reservation>'
select @xml

DECLARE @xmlTable TABLE (
    xmlDoc Xml
);
Insert into @xmltable values (@xml)
--Select xmlDoc from @XmlTable 

Select xmlDoc.value('(//Name)[1]', 'varchar(30)') as Passenger,
       XmlData2.xmlDoc2.query('.') as XmlData2,
       XmlData2.xmlDoc2.value('./@seq', 'int') as LegSeq,
       XmlData3.xmlDoc3.query('.') as XmlData3,
       XmlData3.xmlDoc3.value('.', 'varchar(20)') as Flight
FROM @xmlTable as t
     CROSS APPLY 
        t.xmlDoc.nodes('//Leg') AS XmlData2(xmlDoc2)
     CROSS APPLY 
        t.xmlDoc.nodes('//Flight') AS XmlData3(xmlDoc3)

Проблема в том, что мне все еще нужно вернуть 3 строки, но теперь я получаю 6.

введите здесь описание изображения

Ожидаемый результат:

Neal LegSeq=1 Flight=12 
Neal LegSeq=2 Flight=34
Neal LegSeq=2 Flight=56

Microsoft SQL Server 2019 (окончательная первоначальная версия) — 15.0.2000.5 (X64) 24 сентября 2019 г. 13:48:23 Copyright (C) Microsoft Corporation Developer Edition 2019 (64-разрядная версия) в Windows Server 2019 Standard 10.0 (сборка 17763:)


person NealWalters    schedule 25.05.2020    source источник
comment
Привет, Нил, пожалуйста, включите ожидаемый результат. Существует множество способов создать три строки, которые не описывают, каким должен быть ваш вывод на самом деле.   -  person TT.    schedule 26.05.2020
comment
Добавлены ожидаемые результаты. Я думал, что это очевидно из вопроса и иерархии данных XML. Существует один пассажир, два этапа полета и три номера рейса. Первый этап полета имеет один номер рейса, а второй этап полета имеет два номера рейса.   -  person NealWalters    schedule 26.05.2020


Ответы (1)


Во втором приложении вы хотите применить к узлам из XmlData2.xmlDoc2. Как вы написали, он снова ищет узлы из корня, что будет применяться ко всем элементам Flight в XML.

DECLARE @xml XML='
<Reservation>
  <Name>Neal</Name>
    <Leg seq=''1''>
      <Flight>12</Flight>
    </Leg>
    <Leg seq=''2''>
      <Flight>34</Flight>
      <Flight>56</Flight>
    </Leg>
</Reservation>'
select @xml

DECLARE @xmlTable TABLE (
    xmlDoc Xml
);
Insert into @xmltable values (@xml)
--Select xmlDoc from @XmlTable 

Select xmlDoc.value('(//Name)[1]', 'varchar(30)') as Passenger,
       XmlData2.xmlDoc2.query('.') as XmlData2,
       XmlData2.xmlDoc2.value('./@seq', 'int') as LegSeq,
       XmlData3.xmlDoc3.query('.') as XmlData3,
       XmlData3.xmlDoc3.value('.', 'varchar(20)') as Flight
FROM @xmlTable as t
     CROSS APPLY 
        t.xmlDoc.nodes('//Leg') AS XmlData2(xmlDoc2)
     CROSS APPLY 
        XmlData2.xmlDoc2.nodes('Flight') AS XmlData3(xmlDoc3);
person TT.    schedule 26.05.2020
comment
Ах, я должен был подумать об этом. Как и в случае соединения, каждое перекрестное применение обычно представляет собой отдельный элемент. - person NealWalters; 26.05.2020