2

这是我的伪查询:

SELECT col1, col2 FROM table WHERE number IN(number1,number2,number3);

例子

SELECT name, description FROM products WHERE 5 IN(category_id);

注意:让我们假设表中的行之一的category_id = 2,5,7

问题

如果行在逗号分隔集的开头有“5”,则我的查询有效,如下所示:5,2,7 但如果行以 5 以外的任何值开头,则相同的查询不会返回任何结果。

我尝试了各种场景,在我看来,当 mysql 遇到逗号时,它不再进一步检查逗号分隔数字中的匹配项。

我检查了所有有意义的内容,例如格式正确的逗号分隔字符串和排序规则。在这一点上让我很困惑。有什么解决办法吗?

请注意,我使用FIND_IN_SET()过并且效果很好。但是,我仍然不满足于在IN()不知道真正问题是什么的情况下放弃。为什么它在第一次遇到 fa 逗号时停止。

4

3 回答 3

3

为什么它只对第一个值起作用?

为了将字符串值与数字列进行比较,mysql 将单个字符串值转换为单个数字。当 mysql 将字符串转换为数字时,它会丢弃从第一个非数字字符开始的所有内容,例如:

  • "1234,5678"-->1234
  • "abc5678"-->0

这就是为什么只有第一个数字是有效的。

如果您将字符串值更改为字符串值列表,它将起作用:

 SELECT name, description FROM products WHERE 5 IN ('2', '5', '7');
于 2014-09-29T02:33:49.527 回答
3

IN适用于一值,而不是单个逗号分隔的字符串值。提供给 IN 的每个单独的值都是集合中的一个元素

MySQL 提供了一个可以在这里使用的非标准FIND_IN_SET(str, strlist)函数,尽管适当的关系数据库设计将规范化该字段。

如果字符串 str 在由 N 个子字符串组成的字符串列表 strlist 中,则返回 1 到 N 范围内的值。字符串列表是由以“,”字符分隔的子字符串组成的字符串。

例子:

WHERE FIND_IN_SET('5', category_id)

一个问题,除了破坏规范化和抛弃参照完整性之外,是 FIND_IN_SET不能使用索引,因此在用作高基数选择器时不可扩展。

另请参阅FIND_IN_SET() 与 IN()

于 2014-09-29T02:01:48.257 回答
2

编辑此答案中的表达式示例完全基于字符串上下文,即字符数据类型的比较。这些示例没有考虑隐式数据类型转换,以及字符串到数字转换的古怪 MySQL 语义,例如'2,5,7'+0计算为整数值 2。有关该行为的演示,请参阅 Bohemian 的优秀答案。)


表中的行具有类别值 '2,5,7'。那是一个字符串值。

表达方式:

'5' IN ('2,5,7') 

相当于

'5' = '2,5,7'

字符串值中的逗号被视为 SQL 文本,它们是字符串中的字符。

要使用 获得您要查找的结果IN,您需要这样的表达式:

'5' IN ('2','5','7')

那是三个单独的值,用逗号分隔,它们是 SQL 文本的一部分。这相当于:

( '5' = '2'  OR '5' = '5' OR '5' = '7' )

要回答您提出的问题:

问:为什么第一次遇到逗号就停止?

A:它不会在第一个逗号处停止。它将整个字符串作为单个字符串进行比较。使用此表达式您会得到相同的结果。

'5' IN ('5,2,7') 

这将返回 FALSE,因为它等价于表达式 '5' = '5,2,7'`,并且被比较的两个字符串不相等。

编辑:上面的示例基于字符串比较。在数字上下文中,字符串'5,2,7'将计算为数值 5。

在这种情况下,它仍然不是IN在第一个逗号处停止,而是从字符串到数字的隐式转换“在第一个逗号处停止”。(不仅仅是逗号,它是任何遇到的字符串无法再转换为数值的字符,可以是括号、“#”、“b”或其他任何字符。)

底线:比较运算符IN不会给出关于字符串中逗号字符的老鼠的@ss。这些只是字符串中的字符。字符串值中逗号不会被解释为 SQL 文本的一部分。

于 2014-09-29T02:09:26.130 回答