【问题标题】:Find if a list contains several values - SQL Server Xquery查找列表是否包含多个值 - SQL Server Xquery
【发布时间】:2018-05-14 18:02:35
【问题描述】:

我将 XML 数据存储到名为 BikeTable 的表中。 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>

我希望能够在我的表中找到将包含例如 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 的记录等。

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

【问题讨论】:

    标签: sql-server xquery-sql


    【解决方案1】:

    是的,你可以。不过,这有点猜测,因为您说您想做SELECT *;如果没有表的 DDL,就不可能提供任何数据。因此,相反,我退回了自行车的笼子和 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;
    

    【讨论】:

    • 感谢您的回答。我想我没有很好地解释我的问题,或者我没有理解您的查询。我看不到如何找到包含特定值的记录,例如“Mountain”或“Mountain OR Road”
    • 您的问题是“有什么方法可以知道一个列表是否包含多个值?”,这就是该查询的作用:它返回具有多个 @ 值的值987654323@。这就是为什么预期的结果非常重要。也许您现在需要使用WHEREIN,并摆脱GROUP BYHAVING。更详细地更新您的问题,并让我知道,我会很乐意查看;但我无法做出比我已经拥有的更多的猜测。 :)
    • 是的,很抱歉,我的问题不够清楚。我用更多细节更新了它。并使用您的请求和您的评论,我能够得到第一个结果。我现在想知道的一件事是性能。
    • @Guigui 如果您正在使用text(),那么x-query 应该会执行得很好。如果您不使用text(),那么这实际上会增加查询的额外开销(我不记得具体原因,抱歉)。
    猜你喜欢
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    相关资源
    最近更新 更多