查找列表是否包含多个值 - SQL Server Xquery

Find if a list contains several values - SQL Server Xquery

我正在将 XML 数据存储到名为 BikeTable 的 table 中。 XML 数据来自使用 .Net 序列化程序序列化的对象。 BikeTable 看起来像这样:

Id - UniqueIdentifier
XmlData - XML

存储在 XmlData 列中的 XML 如下所示:

记录 1 :

<Bike>
    <Material>
        <Cage>EIECH</Cage>
        <Mpn>B258-C436-B001</
    </Material>
    <Roles>
        <string>Race</string>
        <string>Mountain</string>
        <string>City</string>
    </Roles>
</Bike>

记录 2 :

<Bike>
    <Material>
        <Cage>ABCDE</Cage>
        <Mpn>B258-C436-B001</Mpn>
    </Material>
    <Roles>
        <string>Race</string>
    </Roles>
</Bike>

我希望能够在我的 table 中找到包含例如 Race 和 Mountain 的记录。

例如,如果我想要包含“Road”和“Mountain”的记录的 ID,我找到的唯一方法是这样的:

select Id 
from BikeTable
where XmlData.exist('/Bike/Roles/string[contains(., "Road")]') = 1 
   or XmlData.exist('/Bike/Roles/string[contains(., "Mountain")]') = 1

我不喜欢这个选项,因为如果我想查找与一个或多个角色匹配的记录,它会强制我生成查询。 角色可以包含无限数量的值,我需要能够找到一个或多个值的记录。 例如:包含 Race 的记录,包含 Race 或 Montain 的记录,包含 City 的记录,包含 City 和 Mountain 等的记录

有什么方法可以知道一个列表是否包含多个值?

是的,你可以。不过,这有点猜测,因为你说你想做一个 SELECT *;如果没有 table 的 DDL,就不可能提供任何数据。因此,相反,我退还了自行车的 Cage 和 Mpn:

CREATE TABLE BikeTable (xmlData xml);

--The Close tag for Mpn was missing in your sample data, I assume it wasn't mean to be
INSERT INTO BikeTable
VALUES('<Bike>
    <Material>
        <Cage>EIECH</Cage>
        <Mpn>B258-C436-B001</Mpn>
    </Material>
    <Roles>
        <string>Race</string>
        <string>Mountain</string>
        <string>City</string>
    </Roles>
</Bike>')
GO
WITH Bikes AS (
    SELECT B.Material.value('(Cage/text())[1]','varchar(15)') AS Cage, --Data Type guessed
           B.Material.value('(Mpn/text())[1]','varchar(15)') AS Mpn, --Data Type guessed
           BR.String.value('(./text())[1]','varchar(15)') AS String --Data Type guessed
    FROM BikeTable BT
         CROSS APPLY BT.xmlData.nodes('/Bike/Material') B(Material)
         CROSS APPLY BT.xmlData.nodes('/Bike/Roles/string') BR(String))
SELECT Cage, Mpn
FROM Bikes
GROUP BY Cage, Mpn
HAVING COUNT(String) > 1;

GO

DROP TABLE BikeTable;