2011-02-17 198 views
54

我在我的表SHIRTS中有一個字段COLORS (varchar(50)),其中包含逗號分隔的字符串,如1,2,5,12,15,。每個數字代表可用的顏色。MySQL查詢查找逗號分隔字符串中的值

當運行查詢select * from shirts where colors like '%1%'以獲得所有紅色襯衫(color = 1)時,我也會得到顏色爲灰色(= 12)和橙色(= 15)的襯衫。

我該如何重寫查詢,以便僅選擇顏色1而不是所有包含數字1的顏色?

+5

我可以通過正則表達式來做到這一點,但更好的解決方案是將襯衫的顏色分解成單獨的表格(顏色),並使用顏色/襯衫的ID來連接它們來使用連接表格(shirt_colors)。 – ceejayoz 2011-02-17 18:36:50

+0

我不能相信6答案*沒有*他們提到MySQL的SET數據類型.. – ColinM 2012-12-14 15:30:51

+0

檢查此: http://stackoverflow.com/questions/12559876/finding-exact-value-from-a-comma -separated-string-in-php-mysql – Alireza 2014-06-28 06:55:14

回答

125

經典的方法是逗號添加到左,右:

select * from shirts where CONCAT(',', colors, ',') like '%,1,%' 

find_in_set也適用:

select * from shirts where find_in_set('1',colors) <> 0 
20

看看的用於MySQL的FIND_IN_SET函數。

SELECT * 
    FROM shirts 
    WHERE FIND_IN_SET('1',colors) > 0 
+0

注意:set中的find不使用表上的索引。 – edigu 2017-02-25 13:43:44

3

你應該真正解決您的數據庫模式,讓您有三個表:

shirt: shirt_id, shirt_name 
color: color_id, color_name 
shirtcolor: shirt_id, color_id 

然後,如果你想找出所有紅色的襯衫,你會做一個查詢,如:

SELECT * 
FROM shirt, color 
WHERE color.color_name = 'red' 
    AND shirt.shirt_id = shirtcolor.shirt_id 
    AND color.color_id = shirtcolor.color_id 
+8

@Bindy:如果你認爲OP有對數據庫模式的編輯權限,有時間重新設計數據庫,遷移數據並重構所有客戶端;並且該查詢的複雜度的降低超過了應用程序其餘部分的複雜度的增加。 – Andomar 2011-02-17 19:30:16

+1

@Andomar,然後再當他會碰到大小限制行檢索和他的「記錄」將得到剪裁,這時候真正的樂趣開始! – Blindy 2011-02-17 21:11:12

20

FIND_IN_SET是你在這種情況下

select * from shirts where FIND_IN_SET(1,colors) 
8

這將肯定工作的朋友,其實我嘗試過了:

[email protected] (DB test) :: DROP TABLE IF EXISTS shirts; 
Query OK, 0 rows affected (0.08 sec) 

[email protected] (DB test) :: CREATE TABLE shirts 
    -> (<BR> 
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    -> ticketnumber INT, 
    -> colors VARCHAR(30) 
    ->);<BR> 
Query OK, 0 rows affected (0.19 sec) 

[email protected] (DB test) :: INSERT INTO shirts (ticketnumber,colors) VALUES 
    -> (32423,'1,2,5,12,15'), 
    -> (32424,'1,5,12,15,30'), 
    -> (32425,'2,5,11,15,28'), 
    -> (32426,'1,2,7,12,15'), 
    -> (32427,'2,4,8,12,15'); 
Query OK, 5 rows affected (0.06 sec) 
Records: 5 Duplicates: 0 Warnings: 0 

[email protected] (DB test) :: SELECT * FROM shirts WHERE LOCATE(CONCAT(',', 1 ,','),CONCAT(',',colors,',')) > 0; 
+----+--------------+--------------+ 
| id | ticketnumber | colors  | 
+----+--------------+--------------+ 
| 1 |  32423 | 1,2,5,12,15 | 
| 2 |  32424 | 1,5,12,15,30 | 
| 4 |  32426 | 1,2,7,12,15 | 
+----+--------------+--------------+ 
3 rows in set (0.00 sec) 

給它是一個嘗試!

6

如果一組顏色或多或少是固定的,最有效和最可讀的方法是在您的應用中使用字符串常量,然後在您的查詢中使用MySQL的SET類型和FIND_IN_SET('red',colors)。當使用SET類型和FIND_IN_SET時,MySQL使用一個整數來存儲所有值,並使用二進制"and"操作來檢查值是否比掃描逗號分隔字符串更有效。

SET('red','blue','green')'red'將內部存儲爲1'blue'將內部作爲2存儲和'green'將內部作爲4被存儲。值'red,blue'將被存儲爲31|2)和'red,green'作爲51|4)。

-4

所有的答案是不是真的正確,試試這個:

select * from shirts where 1 IN (colors); 
0
select * from shirts where find_in_set('1',colors) <> 0 

對我的作品

0

您可以通過下面的函數實現這一目標。

運行以下查詢來創建函數。

DELIMITER || 
CREATE FUNCTION `TOTAL_OCCURANCE`(`commastring` TEXT, `findme`  VARCHAR(255)) RETURNS int(11) 
NO SQL 
-- SANI: First param is for comma separated string and 2nd for string to find. 
return ROUND ( 
    (
     LENGTH(commastring) 
     - LENGTH(REPLACE (commastring, findme, "")) 
    )/LENGTH(findme)   
); 

而且這樣調用

msyql> select TOTAL_OCCURANCE('A,B,C,A,D,X,B,AB', 'A'); 

這個功能希望這會有所幫助。