web-dev-qa-db-fra.com

MySQL find_in_set avec plusieurs chaînes de recherche

Je trouve que find_in_set recherche uniquement par une seule chaîne: - 

find_in_set('a', 'a,b,c,d')

Dans l'exemple ci-dessus, "a" est la seule chaîne utilisée pour la recherche.

Existe-t-il un moyen d'utiliser le type de fonctionnalité find_in_set et d'effectuer une recherche par plusieurs chaînes, comme par exemple: - 

find_in_set('a,b,c', 'a,b,c,d')

Dans l'exemple ci-dessus, je souhaite effectuer une recherche selon trois chaînes 'a, b, c'.

Je vois l’utilisation deOU

find_in_set('a', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d')

Y a-t-il un autre moyen que celui-ci?

37
Mukesh Chapagain

il n'y a pas de fonction native pour le faire, mais vous pouvez atteindre votre objectif en utilisant l'astuce suivante

WHERE CONCAT(",", `setcolumn`, ",") REGEXP ",(val1|val2|val3),"
84
Pavel Perminov

La fonction MySQL find_in_set() ne peut rechercher qu’une chaîne dans un ensemble de chaînes.

Le premier argument est une chaîne, il n'y a donc aucun moyen de lui faire analyser votre chaîne séparée par des virgules en chaînes (vous ne pouvez pas utiliser les virgules dans les éléments SET!). Le deuxième argument est un SET, qui à son tour est représenté par une chaîne séparée par des virgules, d'où votre souhait de find_in_set('a,b,c', 'a,b,c,d') qui fonctionne bien, mais il ne peut sûrement pas trouver une chaîne 'a,b,c' dans aucun SET par définition - il contient des virgules.

14
Dmitry Avtonomov

Vous pouvez également utiliser cette fonction personnalisée

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, ''); 

DELIMITER $$
    CREATE FUNCTION `FIND_SET_EQUALS`(`s1` VARCHAR(200), `s2`  VARCHAR(200)) 
    RETURNS TINYINT(1)
    LANGUAGE SQL
    BEGIN
          DECLARE a INT Default 0 ;
            DECLARE isEquals TINYINT(1) Default 0 ;
          DECLARE str VARCHAR(255);
          IF s1 IS NOT NULL AND s2 IS NOT NULL THEN
             simple_loop: LOOP
                 SET a=a+1;
                 SET str= SPLIT_STR(s2,",",a);
                 IF str='' THEN
                    LEAVE simple_loop;
                 END IF;
                 #Do  check is in set
                 IF FIND_IN_SET(str, s1)=0 THEN
                    SET isEquals=0;
                     LEAVE simple_loop;
                 END IF;
                 SET isEquals=1;
            END LOOP simple_loop;
          END IF;
        RETURN isEquals;
    END;
    $$
    DELIMITER ;

SELECT FIND_SET_EQUALS('a,c,b', 'a,b,c')- 1
SELECT FIND_SET_EQUALS('a,c', 'a,b,c')- 0
SELECT FIND_SET_EQUALS(null, 'a,b,c')- 0
1
user3740702

Vous pouvez également utiliser la commande like par exemple:

where setcolumn like '%a,b%'

ou 

where 'a,b,c,d' like '%b,c%'

qui pourrait fonctionner dans certaines situations.

0
Jon Gabrielson