【问题标题】:MySQL IN() function not workMySQL IN() 函数不起作用
【发布时间】:2014-11-05 13:56:37
【问题描述】:

我有一个奇怪的问题。 MySQL 数据库上的 IN() 函数停止工作。

我的表结构如下:

| id | name  | categories |
---------------------------
| 1  | User1 | 1, 12, 55  |
---------------------------
| 2  | User2 | 12, 55, 76 |
---------------------------
| 3  | User3 | 1, 55, 76  |

要按特定类别列出用户,我大致如下:

SELECT * FROM `users` WHERE `categories` IN ('1','12','55')

或仅来自一个类别:

SELECT * FROM `users` WHERE `categories` IN ('76')

问题是,如果我只询问一个参数,我就得不到任何结果。如果要求更多参数,则仅按列表中的第一个 ID 列出用户,其他不列出。

以前我没有这种问题。我不明白我在哪里犯错误。谢谢!

编辑:

感谢@Andreas Hauser,我终于得到了正确的结果。

这是解决方案:

SELECT * FROM users WHERE FIND_IN_SET ('76',REPLACE(categories,' ',''));

这完全可以正常工作。

其他解决方案非常聪明和有用,我将在未来使用它们,尤其是来自@Justinas 的解决方案和来自@Bilal Rao 的用于搜索类别数组的建议:

SELECT `u`.* FROM `user` `u` JOIN `category` `c` ON `c`.`user_id` = `u`.`id` WHERE `c`.`id` IN ('1', '5', '58');

谢谢大家的帮助!

【问题讨论】:

  • IN() 预计您的列 categories 仅包含一个数字。
  • 您需要规范化您的数据库。每个字段应该只包含一条信息,而不是一个列表。
  • 我要在数组中搜索指定的ID号,并显示结果。

标签: php mysql pdo mysqli


【解决方案1】:

在这种情况下,您必须使用 FIND_IN_SET。

SELECT * FROM `users` WHERE FIND_IN_SET ('76',categories);

这将列出所有类别为 76 的用户。

【讨论】:

  • 次要的一点是 FIND_IN_SET 需要一个逗号分隔的列表来搜索,在这种情况下,OP 的值由逗号和空格分隔
  • 这可能可以通过在 FIND_IN_SET 中放置一个 REPLACE 来解决? SELECT * FROM users WHERE FIND_IN_SET ('76',REPLACE(categories,' ',''));
  • 它可以(我之前已经做过很多次了),但这是一个额外的开销。最好只进行一次替换以删除表上的空格(而不是在查询中),但从长远来看,更好的解决方案是规范化数据库,将值拆分到不同的表中。
  • 这很棒,正是我需要的。只有我需要删除数字之间的空格???
  • 正确。 "UPDATE users SET categories = REPLACE(categories,' ','')"
【解决方案2】:

这仅适用于数值字段 ID 或精确字符串,其中值超过您搜索的值。

您有一个逗号分隔的列表。从该表中获取数据并不是很好。当您有一个字符串时,您必须使用 LIKE

进行搜索

like 的问题在于,当您搜索 %7% 时,您也会搜索 7、77、777。

你可以使用FIND_IN_SET

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

【讨论】:

  • 我就是这样工作的,只是因为我对结果有疑问。
【解决方案3】:

您的类别列中有逗号分隔值,并且 IN 仅适用于完全匹配。请创建另一个表并将这些逗号分隔值放置为 一对多 关系。这样您就可以通过使用 IN 运算符的 Inner Join 来访问它们。

【讨论】:

  • 是的,但是在这个网站上,用户可以选择 ~100 个类别,如果您有 ~37.000 个用户 * 100 个类别,那么您在搜索时会遇到很多问题。这就是为什么我想避免这样的事情。
  • 您可以通过将列设为索引来避免这种情况。但如果你选择 FIND_IN_SET 它将以 LIKE 运算符的方式工作。这就是为什么 INNER JOIN 比通配符查询更好的原因,而且 FIND_IN_SET 只需要两个参数,而你可以在 IN 运算符中提供多个参数。
  • 我需要完全重做插件,这是非常复杂的搜索,我想要一个快速的解决方案,但我需要在多个搜索选项上应用一次。谢谢!
【解决方案4】:

categories 列的类型为 VARCHAR,单个单元格看起来像 "1, 12, 55"
IN 运算符用于每个单元格的单个条目。也就是说,如果您使用 id IN (1, 5, 6),它将获得 ID 为 1、5 和/或 6 的元素。
现在要在字符串中搜索,请使用 LIKE 运算符

 SELECT * FROM `user` WHERE `categories` LIKE "%58%"

但它会选择任何以58 作为组件的条目:125858641586 等等。

最好使用数据透视表。

user_id | category_id
----------------------
    1   |     5
    1   |     6
    2   |     58

比使用查询:

SELECT u.* FROM user u JOIN category c ON c.user_id = u.id WHERE c.id IN (1, 5, 58)

【讨论】:

  • 谢谢!我将使用此解决方案搜索多个类别。
猜你喜欢
  • 2012-07-28
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-23
  • 2013-01-26
  • 2013-01-03
相关资源
最近更新 更多