【问题标题】:Why doesn't this mysql IN (1,2,3,4...) condition work if there are many values in the parenthesis?如果括号中有很多值,为什么这个 mysql IN (1,2,3,4...) 条件不起作用?
【发布时间】:2010-10-06 20:07:45
【问题描述】:

我在列中存储了一个以逗号分隔的状态列表:

像这样:1,2,3,4,5,6,7,8.. 等等,只是它们的 ID。

然后我进行查询以获取状态 ID 为 8 的所有行,并且当状态列表中的项目很少时它可以工作。

这是查询和表格:

mysql> select id_partner, name, states from partner where 8 IN (states);
+------------+----------------+--------------------+
| id_partner | name           | states             |
+------------+----------------+--------------------+
|          1 | Inmo Inmo      | 8,9,10             |
|          2 | Foto Piso      | 8,9,10,11,12,13,14 |
|          4 | PARTNER 001-A  | 8                  |
|          6 | EnAlquiler     | 8                  |
|          7 | Habitaclia.com | 8,43,50            |
+------------+----------------+--------------------+
5 rows in set (0.00 sec)

如果列状态包含 10 个以逗号分隔的 ID,它将起作用,但如果它有 50 个或更多,它将不再起作用。在上面的结果中,它不会显示具有许多状态的行,包括 ID 为 8 的行。

有什么想法吗?我使用这种方法不必创建另一个表来保存合作伙伴和州之间的关系,还是应该做得更好?

【问题讨论】:

    标签: mysql sql database denormalized


    【解决方案1】:

    这不是 IN 子句的工作方式——您需要使用 FIND_IN_SET function 在单个列中搜索逗号分隔值:

    SELECT *  
      FROM partner 
     WHERE FIND_IN_SET(8, states) > 0
    

    实际上,您不应该存储逗号分隔的数据。它被称为非规范化数据,很难在逗号中获取有关特定值的信息。

    【讨论】:

    • 感谢它正在工作! :D 我不知道这一点,所以 IN 条件仅在您执行子查询时才起作用..
    • 对于 WHERE 字段不在 (1,2,3..) 中的情况如何? NOT FIND_IN_SET?
    • @Alexandru Trandafir Catalin:要查找该值是否不在 CSV 中,请使用:WHERE FIND_IN_SET(8, states) = 0 查找 8 不在 CSV 中的行。
    【解决方案2】:

    您的字符串是单个值,而不是多个值。它恰好包含逗号,但它仍然是一个字符串。

    数字上下文中字符串的值取自前导数字。换句话说,'123,456,789' 的数值是 123。MySQL 会忽略第一个非数字之后的所有字符。 (这是 MySQL 中的行为,其他数据库的行为可能不同)。

    IN( ) 谓词允许您比较多个值,但您必须使它们成为单独的 SQL 表达式。例如,在以下两个查询中,只有第一个查询返回任何内容:

    SELECT * FROM partner WHERE 5 IN ( 1, 2, 3, 4, 5 );
    
    SELECT * FROM partner WHERE 5 IN ( '1,2,3,4,5' );
    

    这说明了为什么您不应该使用带有逗号分隔元素的字符串并期望它的行为就像它实际上是单独值的集合的众多原因之一。

    在这种情况下,更好的设计是将给定伙伴的状态存储在另一个表中,其中伙伴和状态之间的每个关联都位于单独的行中。

    create table partner_states (
     id_partner int not null,
     id_state   int not null,
     primary key (id_partner, id_state)
    );
    

    然后填充它:

    insert into partner_states (id_partner, id_state)
    values (1, 8), (1, 9), (1, 10);
    

    然后就可以轻松查询到符合某个状态的伙伴了:

    select id_partner, name, states 
    from partner p join partner_states s on p.id_partner = s.id_partner
    where s.id_state = 8
    

    查询与您可以通过外部联接执行的状态匹配的合作伙伴:

    select id_partner, name, states 
    from partner p left outer join partner_states s on p.id_partner = s.id_partner
      and s.id_state = 8
    where s.id_state is null
    

    【讨论】:

      猜你喜欢
      • 2018-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 2012-02-22
      • 2012-09-28
      • 1970-01-01
      • 2017-02-02
      • 2023-03-30
      相关资源
      最近更新 更多