Requête MySQL pour trouver des valeurs dans une chaîne séparée par des virgules

J’ai un champ COLORS (varchar(50)) dans un ma table SHIRTS qui contient une chaîne délimitée par des virgules comme 1,2,5,12,15, Chaque numéro représentant les couleurs disponibles.

Lorsque vous exécutez la requête, select * from shirts where colors like '%1%' pour obtenir toutes les chemises rouges (couleur = 1), je reçois également les chemises de couleur grise (= 12) et orange (= 15).

Comment dois-je réécrire la requête de manière à ce qu’elle sélectionne UNIQUEMENT la couleur 1 et pas toutes les couleurs contenant le numéro 1?

La manière classique serait d’append des virgules à gauche et à droite:

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

Mais find_in_set fonctionne également:

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

FIND_IN_SET est votre ami dans ce cas

 select * from shirts where FIND_IN_SET(1,colors) 

Jetez un coup d’oeil à la fonction FIND_IN_SET pour MySQL.

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

Cela fonctionnera à coup sûr et je l’ai effectivement essayé:

 lwdba@localhost (DB test) :: DROP TABLE IF EXISTS shirts; Query OK, 0 rows affected (0.08 sec) lwdba@localhost (DB test) :: CREATE TABLE shirts -> (
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -> ticketnumber INT, -> colors VARCHAR(30) -> );
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)

Essaie !!!

Si le jeu de couleurs est plus ou moins fixe, le moyen le plus efficace et le plus lisible serait d’utiliser des constantes de chaîne dans votre application, puis d’utiliser le type SET de MySQL avec FIND_IN_SET('red',colors) dans vos requêtes. Lorsque vous utilisez le type SET avec FIND_IN_SET , MySQL utilise un entier pour stocker toutes les valeurs et utilise les opérations "and" binarys pour vérifier la présence de valeurs beaucoup plus efficaces que le balayage d’une chaîne séparée par des virgules.

Dans SET('red','blue','green') , 'red' serait stocké en interne comme 1 , 'blue' serait stocké en interne comme 2 et 'green' serait stocké en interne comme 4 . La valeur 'red,blue' serait stockée sous la forme 3 ( 1|2 ) et 'red,green' sous la forme 5 ( 1|4 ).

Si vous utilisez MySQL, il existe une méthode REGEXP que vous pouvez utiliser …

http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp

Alors, vous utiliseriez:

 SELECT * FROM `shirts` WHERE `colors` REGEXP '\b1\b' 

Vous devez en fait corriger votre schéma de firebase database de manière à disposer de trois tables:

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

Ensuite, si vous souhaitez trouver toutes les chemises rouges, vous devez effectuer une requête comme:

 SELECT * FROM shirt, color WHERE color.color_name = 'red' AND shirt.shirt_id = shirtcolor.shirt_id AND color.color_id = shirtcolor.color_id 
 select * from shirts where find_in_set('1',colors) <> 0 

Travaille pour moi

Vous pouvez y parvenir en suivant la fonction.

Exécutez la requête suivante pour créer une fonction.

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

Et appeler cette fonction comme ça

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

J’espère que ça aiderait.

Toutes les réponses ne sont pas vraiment correctes, essayez ceci:

 select * from shirts where 1 IN (colors);