Рассмотрим XML и SQL:
declare @xml xml = '
<root>
<person id="11272">
<notes for="107">Some notes!</notes>
<item id="107" selected="1" />
</person>
<person id="77812">
<notes for="107"></notes>
<notes for="119">Hello</notes>
<item id="107" selected="0" />
<item id="119" selected="1" />
</person>
</root>'
select Row.Person.value('data(../@id)', 'int') as person_id,
Row.Person.value('data(@id)', 'int') as item_id,
Row.Person.value('data(../notes[@for=data(@id)][1])', 'varchar(max)') as notes
from @xml.nodes('/root/person/item') as Row(Person)
Я получаю:
person_id item_id notes
----------- ----------- -------
77812 107 NULL
77812 119 NULL
11272 107 NULL
Я хочу, чтобы столбец «Заметки» извлекался на основе атрибута @id текущего item
. Если я заменю [@for=data(@id)]
в селекторе на [@for=107]
, конечно, я получу значение Some notes!
в последней записи. Возможно ли это сделать с помощью XPath / XQuery или я лаю здесь не то дерево? Я думаю, что проблема в том, что
XML немного неловко, да, но я не могу изменить его, я боюсь.
Я нашел одно решение, которое работает, но оно кажется ужасно тяжелым для чего-то подобного.
select Item.Person.value('data(../@id)', 'int') as person_id,
Item.Person.value('data(@id)', 'int') as item_id,
Notes.Person.value('text()[1]', 'varchar(max)') as notes
from @xml.nodes('/root/person/item') as Item(Person)
inner join @xml.nodes('/root/person/notes') as Notes(Person) on
Notes.Person.value('data(@for)', 'int') = Item.Person.value('data(@id)', 'int')
and
Notes.Person.value('data(../@id)', 'int') = Item.Person.value('data(../@id)', 'int')
Обновление!
Я понял это! Я новичок в XQuery, но это работает, поэтому я называю это делом :) Я изменил запрос для заметок на:
Item.Person.value('
let $id := data(@id)
return data(../notes[@for=$id])[1]
', 'varchar(max)') as notes