Вопрос

У меня есть такая таблица:

CREATE TABLE MyTable(
    Id [int] IDENTITY(1,1) NOT NULL,
    XmlField xml NULL,
    /// Some other fields
)

Поле XML содержит XML-представление C#. Dictionary<int, string>.Например:

<dictionary>
    <item>
        <key><int>1</int></key>
        <value><string>Web</string></value>
    </item>
    <item>
        <key><int>2</int></key>
        <value><string>Email</string></value>
    </item>
    // more item
</dictionary>

Я хочу выбрать все строки, в которых XmlField содержит (ключ = 1 со значением = «Интернет»), а также содержит (ключ = 2 со значением = «Электронная почта»).

До сих пор мне удалось отфильтровать строки только по одному уникальному совпадению ключа/значения:

SELECT TableId, XmlField FROM MyTable
CROSS APPLY XmlField.nodes('/dictionary/item') x(fields)
WHERE (x.fields.value('(key/int/text())[1]', 'int') = 1 
AND x.fields.value('(value/string/text())[1]', 'varchar(MAX)') = 'Web')

Если я добавлю AND (x.fields.value('(key/int/text())[1]', 'int') = 2 AND x.fields.value('(value/string/text())[1]', 'varchar(MAX)') = 'Email') тогда ничего не возвращается (вполне логично).

Я также старался не использовать CROSS APPLY и сделайте простой фильтр как таковой:

SELECT TableId, XmlField FROM MyTable
WHERE XmlField.exist('/dictionary/item/key/int[text() = 1]') = 1
AND XmlField.exist('/dictionary/item/value/string[text() = "Web"]') = 1

Но тогда это действует как OR и вернет строки, в которых XML содержит две пары ключ-значение, такие как (1, электронная почта) и (2, Интернет).

Это было полезно?

Решение

Что-то вроде этого должно сделать это.

select *
from MyTable as T
where T.XmlField.exist('/dictionary[item[key/int/text() = 1 and value/string/text() = "Web"] and   
                                    item[key/int/text() = 2 and value/string/text() = "Email"]]') = 1
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top