Предложение SQL WHERE с несколькими атрибутами XML - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть таблица в базе данных со столбцом XML. Теперь мне нужно выбрать несколько строк по двум атрибутам из XML. До сих пор я придумал это:

SELECT o.Id 
FROM Objects o 
WHERE o.SerializedObject.value('(/object/param[@id="111"]/@value)[1]', 'varchar(8)') = '-1'
  AND o.SerializedObject.value('(/object/param[@id="222"]/@value)[1]', 'varchar(8)') = '8'

EDIT:

XML похож на:

<object>
   <param id="1" value="111"/>
   <param id="2" value="222"/>
   ...
   <param id="200" value="4545"/>
<object>

Каждый объект имеет ~ 2k параметров.

Мне интересно, есть ли лучший способ сделать это с одним запросом XML.

1 Ответ

0 голосов
/ 17 сентября 2018

Это зависит от вашего XML (вы не показали пример, но я предполагаю, что это что-то вроде EAV).

Вы можете попробовать использовать метод XML .exist():

DECLARE @mockup TABLE(ID INT IDENTITY,Comment VARCHAR(100),SerializedObject XML);
INSERT INTO @mockup VALUES
 ('just one of them','<object><param id="111" value="-1"/></object>')
,('both, but wrong values','<object><param id="111" value="-1"/><param id="222" value="-1"/></object>')
,('both, should fit','<object><param id="111" value="-1"/><param id="222" value="8"/></object>')

SELECT o.Id,o.Comment,o.SerializedObject
FROM @mockup o 
WHERE o.SerializedObject.exist('/object[param[@id="111" and @value="-1"] and param[@id="222" and @value="8"]]')=1;

.exist() здесь самый быстрый, потому что он не возвращает никакого значения. Он просто вернет 1 при первом обнаружении вхождения. Это особенно быстро, когда есть много случаев <param id="111" value="???"> В противном случае вам придется измельчить всю партию и поместить фильтр на весь набор результатов.

И - конечно! - необходимая подсказка: как сказано в комментарии Jeroen Mostert, работа с большими XML может оказаться бутылочным горлышком. Если вам это нужно чаще, вы можете подумать о реляционном дизайне вместо больших XML ...

...