Mysql
 sql >> Database >  >> RDS >> Mysql

Questo può essere fatto in una query MySQL o è necessario farlo in PHP? (lato server)

Questo può essere fatto in sql . Un modo sarebbe usare una "tabella di supporto" con solo numeri interi a cui puoi join i tuoi dati contro per ottenere la tua riga più volte e quindi per estrarre solo il n -esimo sottoelemento.

Prova questo:

-- 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;

Questo ti darà:

+---------------+----+-----------------+
| 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  |                 |
+---------------+----+-----------------+

Ho utilizzato i tuoi dati di esempio a cui mancano alcuni , , motivo per cui il risultato contiene ad es. March 2 Feb 27 . Si noti inoltre che alcune sottovoci sono vuote (poiché i miei dati di esempio includono voci vuote); potresti o meno volerli filtrare. La tua tabella intera dovrà ovviamente contenere numeri almeno fino al numero massimo di elementi che ti aspetti di avere in una qualsiasi delle tue righe (e se contiene uno 0 o numeri negativi, filtrali nel on -clausola).

substring_index(str,delim,count) restituisce la sottostringa dalla stringa str prima del count occorrenze del delimitatore delim . L'istruzione completa per subentry per un numero positivo, restituirà il _int_1_10.id -esimo elemento o, se la stringa ha meno elementi, l'ultimo elemento.

Il on -clause calcola quindi il numero di elementi (contando il numero di , ) per evitare di ottenere più volte l'ultimo elemento. Se la tua stringa non contiene elementi vuoti (come ,, nei miei dati di esempio), non hai bisogno di quella parte ma potresti aggiungere un elemento vuoto per segnare la fine dell'elenco.

Puoi applicare questo codice all'intero set di risultati, ad es. utilizzando

...
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 ...

Funzionerà, ma potrebbe essere lento. Non può utilizzare un indice sullo space*_2_value -colonne e dovrà fare un sacco di unione e valutazione delle stringhe. Tuttavia, non puoi fare molto al riguardo, tranne la normalizzazione dei tuoi dati.

Se è utile farlo in sql probabilmente dipenderà da cosa stai facendo con i dati. Se hai intenzione di visualizzarlo in una tabella html su una pagina web, potrebbe essere sia più semplice che veloce scorrere l'array in php . Per ordinare, filtrare o join il tuo set di risultati, è probabilmente molto più facile da implementare (e probabilmente più veloce) in sql , forse anche se lo stai usando in un framework. Se hai intenzione di aggiornare i valori, sarà molto più facile farlo in php , poiché molto probabilmente sarà un pasticcio in sql (su questo set di risultati).