2010-10-06 47 views
1

我在列中存储用逗号分隔的状态列表:如果括号中有很多值,为什么mysql IN(1,2,3,4 ...)条件不工作?

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

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

回答

1

这不是IN子句是如何工作的 - 你需要使用FIND_IN_SET function搜索在一列逗号分隔值:

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

实际上,你不应该存储逗号分隔的数据。它被称为非规范化数据,并且可能很难获得逗号内特定值的信息。

+0

感谢它的工作! :D我不知道这一点,所以IN条件只适用于你的子查询。 – 2010-10-06 20:14:11

+0

以及如何为WHERE字段NOT IN(1,2,3 ..)?不FIND_IN_SET? – 2010-10-06 20:20:11

+0

@Alexandru Trandafir Catalin:要查找该值是否不在CSV中,请使用:WHERE FIND_IN_SET(8,states)= 0来查找其中8不在CSV中的行。 – 2010-10-06 20:23:40

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