web-dev-qa-db-fra.com

Équivalent de explode () pour utiliser des chaînes dans MySQL

En MySQL, je veux pouvoir rechercher '31 - 7', quand une autre valeur = '7 - 31'. Quelle est la syntaxe que je voudrais utiliser pour séparer les chaînes dans MySQL? En PHP, j'utiliserais probablement explode(' - ',$string) et les mettrais ensemble. Y a-t-il un moyen de faire cela dans MySQL? 

Contexte: Je travaille avec des scores sportifs et je veux essayer des jeux où les scores sont identiques (et à la même date). Le score indiqué pour chaque équipe est comparé à celui de la base de données de son adversaire. 

L'appel MySQL idéal serait:

Where opponent1.date  = opponent2.date
  AND opponent1.score = opponent2.score

(opponent2.score devrait être opponent1.score en arrière).

38
Bob Cavezza

MYSQL n’a pas de fonction explode() comme intégrée. Mais vous pouvez facilement ajouter une fonction similaire à votre base de données et l’utiliser ensuite à partir de requêtes php. Cette fonction ressemblera à:

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

Usage:

SELECT SPLIT_STRING('Apple, pear, melon', ',', 1)

L'exemple ci-dessus retournera Apple. Je pense qu'il sera impossible de retourner un tableau dans MySQL, vous devez donc spécifier quelle occurrence retourner explicitement dans pos. Faites-moi savoir si vous réussissez à l'utiliser.

61
Arman P.

J'essaie avec SUBSTRING_INDEX(string,delimiter,count)

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql'

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'

voir plus sur mysql.com http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substring-index

40
madde74

Vous pouvez utiliser une procédure stockée de cette façon. 

DELIMITER |

CREATE PROCEDURE explode( pDelim VARCHAR(32), pStr TEXT)                                
BEGIN                                
  DROP TABLE IF EXISTS temp_explode;                                
  CREATE TEMPORARY TABLE temp_explode (id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, Word VARCHAR(40));                                
  SET @sql := CONCAT('INSERT INTO temp_explode (Word) VALUES (', REPLACE(QUOTE(pStr), pDelim, '\'), (\''), ')');                                
  PREPARE myStmt FROM @sql;                                
  EXECUTE myStmt;                                
END |   

DELIMITER ;
  • exemple d'appel:

     SET @str  = "The quick brown fox jumped over the lazy dog"; 
     SET @delim = " "; 
    
    CALL explode(@delim,@str);
    SELECT id,Word FROM temp_explode;
    
23
Disha Goyal

Tout d’abord, vous devriez changer la structure de la base de données - le score dans ce cas est une sorte de valeur composite et devrait être stocké dans deux colonnes, par exemple. score_Host, score_guest.


MySQL ne fournit pas l'équivalent de explode() mais dans ce cas, vous pouvez utiliser SUBSTRING() et LOCATE() pour couper le score d'un hôte et d'un invité.

SELECT 
   CONVERT(SUBSTRING(score, 1, LOCATE('-',score) - 2) USING INTEGER) as score_Host,
   CONVERT(SUBSTRING(score, LOCATE('-',score)+2) USING INTEGER) as score_guest
FROM ...;

CONVERT() est utilisé pour convertir une chaîne "23" en nombre 23.

17
Crozin

Utilisez cette fonction. Il fonctionne comme un charme. remplacer "|" avec le caractère à décomposer/scinder et les valeurs 1, 2, 3, etc. sont basés sur le nombre d’entrées dans le fichier: Value_ONE | Value_TWO | Value_THREE.

SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 1), '|', -1) AS PSI,
SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 2), '|', -1) AS GPM,
SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 3), '|', -1) AS LIQUID

J'espère que ça aide.

4
Sergio Rodriguez

Comme @ arman-p l'a fait remarquer, MYSQL n'a pas d'explode (). Cependant, je pense que la solution présentée est beaucoup plus compliquée que nécessaire. Pour effectuer une vérification rapide lorsque vous recevez une chaîne de liste délimitée par des virgules (par exemple, la liste des clés de table à rechercher), procédez comme suit:

SELECT 
    table_key, field_1, field_2, field_3
FROM
    my_table
WHERE
    field_3 = 'my_field_3_value'
    AND (comma_list = table_key
        OR comma_list LIKE CONCAT(table_key, ',%')
        OR comma_list LIKE CONCAT('%,', table_key, ',%')
        OR comma_list LIKE CONCAT('%,', table_key))

Cela suppose que vous ayez également besoin de vérifier field_3 sur la table. Si vous n'en avez pas besoin, n'ajoutez pas cette condition.

2
Al Zziwa

utilisez substring_index, dans l'exemple ci-dessous, j'ai créé un tableau avec la colonne score1 et score2, score1 ayant un score de 3-7, score2 de 7 à 3, etc. comme indiqué dans l'image. La requête ci-dessous peut se scinder en utilisant "-", inverser l'ordre de score2 et comparer à score1. 

SELECT CONCAT(SUBSTRING_INDEX(score1,'-',1),
SUBSTRING_INDEX(score1,'-',-1)) as my_score1,
CONCAT(SUBSTRING_INDEX(score2,'-',-1),SUBSTRING_INDEX(score2,'-',1)) as my_score2
FROM test HAVING my_score1=my_score2

 scores table

 query results

2
philip mudenyo

si explos est utilisé avec foreach pour construire une nouvelle chaîne, vous pouvez simuler exploser en utilisant une boucle while comme ceci:

CREATE FUNCTION explode_and_loop(sep VARCHAR(),inputstring VARCHAR()) RETURNS VARCHAR() 
BEGIN
    DECLARE part,returnstring VARCHAR();
    DECLARE cnt,partsCnt INT();
    SET returnstring = '';
    SET partsCnt = ((LENGTH(inputstring ) - LENGTH(REPLACE(inputstring,sep,''))) DIV LENGTH(sep);
    SET cnt = 0;
    WHILE cnt <= partsCnt DO
        SET cnt = cnt + 1;
        SET part = SUBSTRING_INDEX(SUBSTRING_INDEX(inputstring ,sep,cnt),sep,-1);
        -- DO SOMETHING with the part eg make html:
        SET returnstring = CONCAT(returnstring,'<li>',part,'</li>')
    END WHILE;
    RETURN returnstring;
END

cet exemple renverra une liste HTML des pièces. (il faut ajouter des jambes variables requises)

1
ohjay

J'ai rencontré le même problème aujourd'hui et je l'ai résolu comme suit: veuillez noter que dans mon cas, je connais le nombre d'éléments contenus dans la chaîne concaténée. Je peux donc les récupérer de cette manière:

set @var1=0;
set @var2=0;
SELECT SUBSTRING_INDEX('value1,value2', ',', 1) into @var1;
SELECT SUBSTRING_INDEX('value1,value2', ',', -1) into @var2;

les variables @ var1 et @ var2 auraient les mêmes valeurs que explode ().

0
DoubleA