#sql-server #xml #tsql #xquery
#sql-сервер #xml #tsql #xquery
Вопрос:
У меня есть следующее поле XML ():
<A>
<B name="B1">
<C>
<D name="D1">
<E name="E1"/>
<E name="E2"/>
<E name="E3"/>
</D>
<D name="D2">
<E name="E4"/>
<E name="E5"/>
<E name="E6"/>
</D>
</C>
</B>
<B name="B3">
<C>
<D name="D11">
<E name="E11"/>
<E name="E22"/>
<E name="E33"/>
</D>
<D name="D22">
<E name="E44"/>
<E name="E55"/>
<E name="E66"/>
</D>
</C>
</B>
</A>
Если я хочу использовать nodes()
и value()
получать данные из XML, что мне делать, результат должен быть таким:
B | D | E |
---|---|---|
B1 | D1 | E1 |
B1 | D1 | E2 |
B1 | D1 | E3 |
B2 | D2 | E4 |
.. | ||
B3 | D22 | E66 |
Я попробовал следующий запрос:
SELECT NodePath.value('@name', 'varchar(100)') B,
NodePath.value('(./C/D/@name)[1]', 'varchar(64)') D,
NodePath.value('(./C/D/E/@name)[1]', 'varchar(100)') E
FROM XmlTable xt
cross apply xt.XmlField.nodes('/A/B') Node(NodePath)
но мне кажется, что для этого требуется только одно E из разных B
Комментарии:
1. Пример XML недопустим. В закрывающих тегах должен использоваться
/
символ, а не символ «». например:<D>...</D>
.2. @AlwaysLearning, sry, я это исправил.
Ответ №1:
SELECT NodePath.value('@name', 'varchar(100)') B,
--NodePath.value('(./C/D/@name)[1]', 'varchar(64)') D,
--NodePath.value('(./C/D/E/@name)[1]', 'varchar(100)') E,
d.d.value('@name', 'varchar(64)') AS D,
e.e.value('@name', 'varchar(100)') AS E
FROM XmlTable xt
CROSS APPLY xt.XmlField.nodes('/A/B') AS Node(NodePath)
CROSS APPLY Node.NodePath.nodes('C/D') AS d(d)
CROSS APPLY d.d.nodes('E') AS e(e)
Комментарии:
1. Спасибо, это работает! И мне также интересно его производительность. Будет ли его производительность лучше, чем у следующего запроса?
SELECT NodePath.value(../../../'@name', 'varchar(100)') B, NodePath.value('@../name', 'varchar(64)') AS D, NodePath.value('@name', 'varchar(100)') AS E FROM XmlTable xt CROSS APPLY xt.XmlField.nodes('/A/B/C/D/E') AS Node(NodePath)
2. ..@zening.chen . В общем, перемещение вверх по структуре / иерархии xml (от дочернего узла к родительскому узлу) с использованием parent:: или аббревиатуры ‘../’ является более дорогостоящим / дорогостоящим, чем сначала получение родительского, а затем дочерних элементов. Вы можете сравнить и проверить различия в двух планах выполнения (для подъема по иерархии требуется 2 дополнительных фильтра xpath). Это не означает, что ваше предложение будет медленнее. Более дорогостоящий запрос получает больше памяти, и иногда это может привести к тому, что дорогостоящий запрос будет выполняться быстрее, чем более дешевый. Просто протестируйте его в своей среде и выберите тот, который вам подходит.