2010-10-06 48 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