查找列表是否包含多个值 - 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;
我正在将 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;