SQL IN子句只返回ID列表中第一个匹配的行



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

我正试图从数据库中获取所有在他们的商店访问中有商店ID(例如2(的用户

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

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

E.g

  • 用户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(的情况下实现这一点,那将是理想的。

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

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

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

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

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

where find_in_set('2', shop)

也就是说,我强烈建议修复您的数据模型。在数据库中存储CSV数据在很多方面都会破坏关系数据库的用途。您应该有一个单独的表来存储用户/商店关系,每个元组都在单独的行上。推荐阅读:在数据库列中存储分隔列表真的有那么糟糕吗?。

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

SELECT *
FROM users
WHERE shop_access REGEXP '[[:<:]]2[[:>:]]';
-- [[:<:]] and [[:>:]] are word boundaries
SELECT * FROM users WHERE (shop_access = 2) OR (shop_access LIKE "2,%" OR shop_access LIKE "%,2,%" OR shop_access LIKE "%,2")

相关内容

最新更新