Mysql
 sql >> Base de données >  >> RDS >> Mysql

Cela peut-il être fait dans une requête MySQL ou doit-il être fait en PHP ? (du côté serveur)

Cela peut être fait en sql . Une façon serait d'utiliser une "table d'aide" avec juste des entiers que vous pouvez join vos données pour obtenir votre ligne plusieurs fois, puis pour extraire uniquement le n -ème sous-élément.

Essayez ceci :

-- helper table with a listof integers from 1 to 10
create table _int_1_10 (id int primary key);
insert into _int_1_10 (id) 
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);

-- some example data 
create table test_strexplode (
   id int primary key, 
   space_value_1 varchar(200),
   space_value_2 varchar(200)
);

insert into test_strexplode (id, space_value_1, space_value_2)
values (1, 'row 1', 'March 3,March 5,March 6 March 1,March 2 Feb 27'),
       (2, 'row 2', 'March 3,,March 5'),
       (3, 'row 3', '');

select space_value_1, 
  _int_1_10.id,
  -- extracts the "_int_1_10.id"th element
  SUBSTRING_INDEX(SUBSTRING_INDEX(
       space_value_2,',',_int_1_10.id),',',-1) as subentry
from test_strexplode
join _int_1_10 
on _int_1_10.id <= 
   -- number of elements in your string (= number of "," + 1)
   char_length(space_value_2) - char_length(replace(space_value_2, ',', '')) + 1
order by test_strexplode.id, _int_1_10.id;

Cela vous donnera :

+---------------+----+-----------------+
| space_value_1 | id | subentry        |
+---------------+----+-----------------+
| row 1         | 1  | March 3         | 
| row 1         | 2  | March 5         |
| row 1         | 3  | March 6 March 1 |
| row 1         | 4  | March 2 Feb 27  |
| row 2         | 1  | March 3         |
| row 2         | 2  |                 |
| row 2         | 3  | March 5         |
| row 3         | 1  |                 |
+---------------+----+-----------------+

J'ai utilisé vos exemples de données auxquels il manque certains , , c'est pourquoi le résultat contient par ex. March 2 Feb 27 . Notez également que certaines sous-entrées sont vides (car mes exemples de données incluent des entrées vides); vous pouvez ou non vouloir les filtrer. Votre tableau d'entiers devra évidemment contenir des nombres au moins jusqu'au nombre maximum d'éléments que vous vous attendez à avoir dans l'une de vos lignes (et s'il contient un 0 ou des nombres négatifs, filtrez-les dans le on -clause).

substring_index(str,delim,count) renvoie la sous-chaîne de la chaîne str avant count occurrences du délimiteur delim . La déclaration complète pour subentry renverra, pour un nombre positif, soit le _int_1_10.id -ème élément ou, si la chaîne a moins d'éléments, le dernier élément.

Le on -clause calcule donc le nombre d'éléments (en comptant le nombre de , ) pour éviter d'obtenir plusieurs fois le dernier élément. Si votre chaîne ne contient aucun élément vide (comme le ,, dans mes exemples de données), vous n'avez pas besoin de cette partie, mais vous pouvez ajouter un élément vide pour marquer la fin de la liste.

Vous pouvez appliquer ce code à l'ensemble de vos résultats, par exemple. en utilisant

...
from (select ... 
         space1_1_value as space_value_1,
         space1_2_value as space_value_2
      ...
      union all ... union all ... ) as test_strexplode 
join _int_1_10 ...

Cela fonctionnera, mais cela pourrait être lent. Il ne peut pas utiliser d'index sur le space*_2_value -columns et devra faire beaucoup de jointure et d'évaluation de chaîne. Vous ne pouvez pas faire grand-chose à ce sujet, sauf normaliser vos données.

S'il est utile de le faire en sql dépendra probablement de ce que vous faites avec les données. Si vous allez simplement l'afficher dans un tableau html sur une page Web, il peut être à la fois plus facile et plus rapide de simplement parcourir le tableau en php . Pour trier, filtrer ou join votre jeu de résultats, il est probablement beaucoup plus facile à implémenter (et probablement plus rapide) en sql , peut-être même si vous l'utilisez dans un framework. Si vous allez mettre à jour les valeurs, ce sera beaucoup plus facile à faire en php , car cela va très probablement être un gâchis dans sql (sur cet ensemble de résultats).