Вы уже получили свой ответ, но я хочу указать на тот факт, что обратная навигация (с использованием ../../
) ужасно медленная с большими структурами .
Я бы предложил это:
A макет для имитации вашей проблемы:
DECLARE @yourTable TABLE(ID INT IDENTITY,YourXml XML);
INSERT INTO @yourTable VALUES
(N'<ImageHistory>
<Load targets="2" totalTime="417">
<Orders>
<Order name="20548976" />
</Orders>
<Data>
<Disk SerNr="XXXXXX" Size_mb="228936" LoadSuccessfull="true" />
<Disk SerNr="ZZZZZ" Size_mb="228936" LoadSuccessfull="true" />
</Data>
</Load>
</ImageHistory>');
- Запрос
SELECT t.ID
,ld.value('@targets','int') AS Load_Targets
,ld.value('@totalTime','int') AS Load_TotalTime
,ld.value('(Orders/Order/@name)[1]','int') AS Order_Name
,dsk.value('@SerNr','nvarchar(100)') AS Disk_SerNr
,dsk.value('@Size_mb','nvarchar(100)') AS Disk_Size_mb
,dsk.value('@LoadSuccessfull','bit') AS Disk_LoadSuccessfull
FROM @yourTable AS t
CROSS APPLY t.YourXml.nodes('/ImageHistory/Load') A(ld)
CROSS APPLY A.ld.nodes('Data/Disk') B(dsk);
Идея вкратце:
Первый APPLY
опустится до <Load>
и вернет все <Load>
элементов (если их больше ...
Второй APPLY
будет использовать фрагмент, возвращенный первым APPLY
и нырнуть глубже до <Disk>
.
Мы извлекаем имя ордера (и другие значения), вызывая .value()
против первого фрагмента (который является <Load>
), и мы извлекаем значения <Disk>
, вызывая .value()
против фрагмента второго APPLY
.