SQL IN 子句仅返回以逗号分隔的 ID 列表中具有第一个匹配项的行

Posted

技术标签:

【中文标题】SQL IN 子句仅返回以逗号分隔的 ID 列表中具有第一个匹配项的行【英文标题】:SQL IN Clause only returning rows with first match in comma separated list of IDs 【发布时间】:2020-12-31 22:30:15 【问题描述】:

我有 5 个用户,他们有一列“shop_access”(这是商店 ID 的列表,例如:1、2、3、4)

我正在尝试从数据库中获取所有在其 shop_access 中具有商店 ID(例如 2)的用户

Current Query:
SELECT * FROM users WHERE '2' IN (shop_access)

但是,它只返回 shop_access 以数字 2 开头的用户。

例如

用户 1 管理店铺 1,2,3 用户 2 管理店铺 2,4,5 用户 3 管理店铺 1,3,4 用户 4 管理商店 2,3

运行 IN 子句时将返回的唯一一个是用户 2 和用户 4。

用户 1 被忽略(它不应该因为它在列表中有数字 2),因为它不是以数字 2开始

我目前无法返回并更改设置方式,例如将其转换为 JSON 并首先使用 php 处理它,因此如果有人可以尝试使其工作而无需更改列理想的数据(shop_access)。

【问题讨论】:

请用您正在运行的数据库标记您的问题:mysql、oracle、postgresql...? 您能否更改查询以对用户和商店访问表 WHERE shopid = 2 进行联接? 【参考方案1】:

一个可移植的解决方案是使用like:

where concat(',', shop, ',') like '%,2,%'

或者如果要搜索的值作为参数给出:

where concat(',', shop, ',') like concat('%,', ?, ',%')

根据您的数据库,可能会有更简洁的选项可用。在 MuSQL 中:

where find_in_set('2', shop)

也就是说,我强烈建议您修复您的数据模型。在数据库中存储 CSV 数据在许多方面违背了关系数据库的目的。您应该有一个单独的表来存储用户/商店关系,每个元组在单独的行上。推荐阅读:Is storing a delimited list in a database column really that bad?。

【讨论】:

LIKE '%2%' 应该在您的第一个示例中发挥作用。百分号也会检查空字符串。 @CaptainKenpachi '%2%' 不会成功,因为它也会匹配 12,22,242,... 我不认为这是有意的【参考方案2】:

另外,您可能需要考虑在此处使用REGEXP 作为选项:

SELECT *
FROM users
WHERE shop_access REGEXP '[[:<:]]2[[:>:]]';
                            -- [[:<:]] and [[:>:]] are word boundaries

【讨论】:

【参考方案3】:
SELECT * FROM users WHERE (shop_access = 2) OR (shop_access LIKE "2,%" OR shop_access LIKE "%,2,%" OR shop_access LIKE "%,2")

【讨论】:

尝试在你的答案中加入一点描述/上下文/推理,会更有帮助。

以上是关于SQL IN 子句仅返回以逗号分隔的 ID 列表中具有第一个匹配项的行的主要内容,如果未能解决你的问题,请参考以下文章

如何在选择语句的“NOT IN”子句中使用逗号分隔的字符串列表作为 pl/sql 存储的函数参数

安全地为查询准备逗号分隔列表[重复]

SQL IN 逗号分隔参数与内部查询

从表中选择 WHERE 子句中具有不同 IN 列表的表

在主查询的“IN”子句中使用逗号分隔列表的子查询结果

使用 WHERE IN SQL 子句将字符串值从单个值拆分为多个值以获取数据