#sql #xml #db2 #xquery-sql
#sql #xml #db2 #xquery-sql
Вопрос:
Одна из моих таблиц базы данных содержит несколько записей. В каждой записи есть столбец, в котором хранится XML следующего типа . Мне нужно написать запрос, который должен извлекать записи, в которых внутри родительского узла, если какой-либо из подузлов содержит только значение 0 полностью. В этом примере четвертый узел содержит все 0. Это удовлетворяет условию, и запись должна быть извлечена. Могу ли я узнать, как записать это условие в SQL для извлечения таким образом?
Примечание: родительский узел может содержать несколько подузлов.
XML:
<videoDetails>
<video>
<V1>
<display>0</display>
</V1>
<V2>
<display>0</display>
</V2>
<V3>
<display>0</display>
</V3>
<V4>
<display>0</display>
</V4>
<V5>
<display>1</display>
</V5>
</video>
<video>
<V1>
<display>0</display>
</V1>
<V2>
<display>0</display>
</V2>
<V3>
<display>1</display>
</V3>
<V4>
<display>0</display>
</V4>
<V5>
<display>0</display>
</V5>
</video>
<video>
<V1>
<display>0</display>
</V1>
<V2>
<display>1</display>
</V2>
<V3>
<display>0</display>
</V3>
<V4>
<display>0</display>
</V4>
<V5>
<display>1</display>
</V5>
</video>
<video>
<V1>
<display>0</display>
</V1>
<V2>
<display>0</display>
</V2>
<V3>
<display>0</display>
</V3>
<V4>
<display>0</display>
</V4>
<V5>
<display>0</display>
</V5>
</video>
</videoDetails>
Я попытался использовать что-то вроде NOT xmlexists(‘$ N /../.. / ../videoDetails/video[1] /* [display= 1]’, передавая USER_VIDEO_XML как «N») . Это работает только тогда, когда XML содержит один узел, который имеет все 0 и не работает с несколькими узлами.
Запросите ваши ценные входные данные.
Комментарии:
1. Поддержка XML сильно зависит от поставщика — поэтому, пожалуйста, добавьте тег, чтобы указать, используете ли вы
mysql
,postgresql
,sql-server
,oracle
илиdb2
— или что-то совсем другое.2. ваш XPath заставляет его просматривать только 1-й узел <video>.
.../video[1]...
. это [1] заставляет его игнорировать все остальные. Вы пробовали без указания позиции массива.'$N/../../../videoDetails/video/*[display=1]'
?
Ответ №1:
Используйте следующий запрос:
SELECT 1
FROM MY_TAB T
WHERE XMLCAST(XMLQUERY
(
'
let $d :=
for $v in $doc/videoDetails/video
return fn:exists($v/*[display != 0])
return fn:exists($d[. = fn:false()])
' PASSING T.DOC AS "doc"
) AS INT) = 1
for
Цикл перебирает все video
подузлы и возвращает следующую последовательность в $ d для вашего данного примера:
(true, true, true, false)
4 video
подузла. Первые 3 из них содержат display !=0
, а 4-й — нет. Предложение return
outer возвращает true, если приведенная выше последовательность содержит false
значение. Вы можете поиграть с образцами данных, проверяя результат по следующей ссылке db<>fiddle.