Столбец SQL XML - перекрестное применение для создания нескольких строк на основе XML от 1 до многих

Я изучал это сообщение, но я до сих пор не понимаю «перекрестного применения» с данными XML. Также это сообщение.

У меня есть столбец Xml, содержащий пассажира и несколько рейсов и этапов полета на его билете.

Вот что у меня получилось после долгой возни:

Select xmlDoc.value('(//Passenger[1]/text())[1]', 'varchar(100)') as Passenger,
       XmlData2.xmlDoc2.query('//FlightLeg') as xmlDoc2b
FROM xmlData as t 
CROSS APPLY 
    t.xmlDoc.nodes('//FlightLeg') AS XmlData2(xmlDoc2)
where xmlSchema = 'Reservation'

Это текущий результат. Хорошей новостью является то, что есть три строки, которые соответствуют количеству FlightLegs. введите здесь описание изображения

Данные в каждом результате одинаковы:

<FlightLeg seq="1">
  <FlightNumber>1849</FlightNumber>
  <DepartureAirport>MDW</DepartureAirport>
  <ArrivalAirport>STL</ArrivalAirport>
  <DepartureDateTime>2019-11-02T19:20:00</DepartureDateTime>
  <ArrivalDateTime>2019-11-02T20:25:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="2">
  <FlightNumber>2105</FlightNumber>
  <DepartureAirport>STL</DepartureAirport>
  <ArrivalAirport>OKC</ArrivalAirport>
  <DepartureDateTime>2019-11-02T21:25:00</DepartureDateTime>
  <ArrivalDateTime>2019-11-02T22:50:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="1">
  <FlightNumber>4565</FlightNumber>
  <DepartureAirport>OKC</DepartureAirport>
  <ArrivalAirport>MDW</ArrivalAirport>
  <DepartureDateTime>2019-11-04T11:10:00</DepartureDateTime>
  <ArrivalDateTime>2019-11-04T13:05:00</ArrivalDateTime>
</FlightLeg>

Я стремлюсь к тому, чтобы каждая строка 1 имела первый FlightLeg, строка 2 - вторую и т. Д. Затем после этого я выделю определенные элементы XML в столбцы.

Более простой образец для воспроизведения:

DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
    xmlDoc Xml
);
Insert into @xmltable values (@xml)
Select xmlDoc from @XmlTable 

Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
       XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b
FROM @xmlTable as t
CROSS APPLY 
    t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)

Я мог видеть использование здесь нижнего индекса:

XmlData2.xmlDoc2.query('//Flight[@xxxx]') as xmlDoc2b

но не может использовать RowNumber, придется сбрасывать каждую строку из таблицы.

Теперь я пытаюсь сделать свой SQL похожим на найденный мной образец здесь:

DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
    xmlDoc Xml
);
Insert into @xmltable values (@xml)
--Select xmlDoc from @XmlTable 

-- This was running, but same data on all three rows 
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
       XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b

FROM @xmlTable as t
CROSS APPLY 
    t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)


-- Trying to make above look like blog sample below 
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
       My_XML.FlightTest.query('//Flight') as FlightLegTest
FROM (SELECT xmlDoc 
      FROM @xmlTable as T(My_XML))
      CROSS APPLY My_XML.nodes('//Flight') AS My_XML (FlightTest) 
/* Sample from https://www.mssqltips.com/sqlservertip/5707/simple-way-to-import-xml-data-into-sql-server-with-tsql/ */ 
SELECT
   MY_XML.Customer.query('Name').value('.', 'VARCHAR(50)')
FROM (SELECT CAST(MY_XML AS xml)
      FROM OPENROWSET(BULK 'c:\XMLClass\IntroSamples\BulkLoadCustomers1.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
      CROSS APPLY MY_XML.nodes('Customers/Customer') AS MY_XML (Customer);

Я получаю сообщение об ошибке: неправильный синтаксис рядом с '(' где строка # указывает на эту строку: FROM @xmlTable as T (My_XML))

Пока я не могу понять, почему мы поместили «as x (y)», другими словами, второе значение в круглые скобки; Я все еще изучаю это.

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


person NealWalters    schedule 21.05.2020    source источник
comment
XmlData2.xmlDoc2.query('//Flight') должно быть что-то вроде XmlData2.xmlDoc2.query('.') или XmlData2.xmlDoc2.value('.', 'int') предположительно   -  person Martin Smith    schedule 22.05.2020
comment
Вау, спасибо, вот и все. Затем я получаю оттуда ./FlightNumber. Поэтому, когда расширение не используется, оно начинается с корня всего документа. Я до сих пор нахожу это запутанным. Напишите ответ, если хотите.   -  person NealWalters    schedule 22.05.2020


Ответы (1)


CROSS APPLY 
    t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)

Создает три строки, в которых контекстный узел уже настроен на три полета по очереди. Вам просто нужно использовать . для доступа к нему.

Например, XmlData2.xmlDoc2.query('.') или XmlData2.xmlDoc2.value('.', 'int') как в этом примере db ‹> скрипки

person Martin Smith    schedule 22.05.2020
comment
Отлично, понял! Теперь я пробую 3 уровня иерархии и возвращаю слишком много строк: stackoverflow.com/questions/62008546/ - person NealWalters; 25.05.2020