Запрос MySQL поиск значений в строке, разделенной запятыми
у меня есть поле COLORS (varchar(50)) в таблице SHIRTS который содержит строку с разделителями-запятыми, например 1,2,5,12,15,. Каждое число представляет Доступные цвета.
при выполнении запроса select * from shirts where colors like '%1%' чтобы получить все красные рубашки (цвет=1), я также получаю рубашки, цвет которых серый (=12) и оранжевый (=15).
как я должен переписать запрос, чтобы выбрать только цвет 1, а не все цвета, содержащие число 1?
10 ответов:
классическим способом было бы добавить запятые слева и справа:
select * from shirts where CONCAT(',', colors, ',') like '%,1,%'но find_in_set работает:
select * from shirts where find_in_set('1',colors) <> 0
FIND_IN_SET - ваш друг в этом случае
select * from shirts where FIND_IN_SET(1,colors)
посмотри FIND_IN_SET функция для MySQL.
SELECT * FROM shirts WHERE FIND_IN_SET('1',colors) > 0
Это будет работать наверняка, и я на самом деле попробовал его:
lwdba@localhost (DB test) :: DROP TABLE IF EXISTS shirts; Query OK, 0 rows affected (0.08 sec) lwdba@localhost (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) lwdba@localhost (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 lwdba@localhost (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)дайте ему попробовать !!!
если набор цветов более или менее фиксирован, наиболее эффективным и наиболее читаемым способом было бы использовать строковые константы в вашем приложении, а затем использовать MySQL
SETтипаFIND_IN_SET('red',colors)в ваши запросы. При использованииSETтипа FIND_IN_SET, MySQL использует одно целое число для хранения всех значений и использует binary"and"операция для проверки наличия значений, которая является более эффективной, чем сканирование строки, разделенной запятыми.на
SET('red','blue','green'),'red'будет храниться внутри как1,'blue'будет храниться внутри, как2и'green'будет храниться внутри, как4. Значение'red,blue'будет храниться как3(1|2) и'red,green'как5(1|4).
Если вы используете MySQL, есть метод REGEXP, который вы можете использовать...
http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
тогда вы бы использовали:
SELECT * FROM `shirts` WHERE `colors` REGEXP '\b1\b'
вы должны исправить схему базы данных так, что у вас есть три таблицы:
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
вы можете достичь этого, выполнив следующую функцию.
выполните следующий запрос для создания функции.
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');надеюсь, что это поможет.
Comments