1

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

像这样: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 的行。

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

4

2 回答 2

1

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

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

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

于 2010-10-06T20:11:02.750 回答
1

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

数字上下文中字符串的值取自前导数字。换句话说,'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
于 2010-10-06T20:16:20.780 回答