Ссылка на текущий контекст в T-SQL nodes() XQuery

Можно ли выполнить соединение между двумя вызовами T-SQL nodes(), отфильтровав второй nodes() на основе узла контекста первого?

В приведенном ниже примере я пытаюсь вернуть таблицу, показывающую PersonID, Name и Position. Моя попытка сослаться на @id узла контекста первого nodes() во втором операторе XQuery nodes() не работает. Названия позиций не возвращаются.

Любые идеи?

Благодарю вас!

DECLARE @xml xml  = '<Root>
    <People>
        <Person id="1">Frank</Person>
        <Person id="2">Joe</Person>
    </People>
    <Positions>
        <Position assignedToPerson="1">Engineer</Position>
        <Position assignedToPerson="2">Manager</Position>
    </Positions>
</Root>'

SELECT 
   PersonID = person.value('@id', 'NVARCHAR(50)'),
   Name = person.value('.', 'NVARCHAR(50)'),
   positionTitle = position.value('Position[1]', 'NVARCHAR(50)')
FROM 
   @xml.nodes('/Root/People/Person') People(person)
OUTER APPLY 
   @xml.nodes('/Root/Positions/Position[@assignedToPerson=.[@id]]') Positions(position)

person Ben Gribaudo    schedule 01.08.2014    source источник


Ответы (2)


Использование соединения по значению вместо перекрестного применения по узлу должно работать; positiontitle в проекции становится значением элемента (.):

DECLARE @xml xml  = '<Root>
    <People>
        <Person id="1">Frank</Person>
        <Person id="2">Joe</Person>
    </People>
    <Positions>
        <Position assignedToPerson="1">Engineer</Position>
        <Position assignedToPerson="2">Manager</Position>
    </Positions>
</Root>'

SELECT 
   PersonID = person.value('@id', 'NVARCHAR(50)'),
   Name = person.value('.', 'NVARCHAR(50)'),
   positionTitle = position.value('.', 'NVARCHAR(50)')
FROM 
   @xml.nodes('/Root/People/Person') People(person)
JOIN 
   @xml.nodes('/Root/Positions/Position') Positions(position)
ON person.value('@id', 'NVARCHAR(50)')= 
position.value('@assignedToPerson[1]','NVARCHAR(50)')
person Jayvee    schedule 01.08.2014
comment
Спасибо за ответ, @Jayvee! Это не похоже на то, что я надеялся сделать (возможна ссылка на предыдущий контекст nodes() из XQUERY nodes()). Ваш ответ решает более важную задачу — соединение двух частей документа — поэтому я назначу ему проверку ответа. - person Ben Gribaudo; 05.08.2014

Некоторые незначительные изменения здесь и там, но почти такие же, как то, что написал Jayvee. Я применил LEFT JOIN, чтобы обеспечить выполнение логики OUTER APPLY.

DECLARE @xml xml  = '<Root>
    <People>
        <Person id="1">Frank</Person>
        <Person id="2">Joe</Person>
        <Person id="3">Joe No Manager</Person>
    </People>
    <Positions>
        <Position assignedToPerson="1">Engineer</Position>
        <Position assignedToPerson="2">Manager</Position>
    </Positions>
</Root>'

SELECT   person.value('@id', 'INT') AS PersonID,
         person.value('.', 'NVARCHAR(50)') AS NAME,
         position.value('.', 'NVARCHAR(50)') AS positionTitle
FROM     @xml.nodes('/Root/People/Person') People(person)
LEFT JOIN    @xml.nodes('/Root/Positions/Position') Positions(position)
    ON   person.value('@id', 'INT') = position.value('@assignedToPerson', 'INT')
person Gouri Shankar Aechoor    schedule 03.08.2014