Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Isso pode ser feito em uma consulta MySQL ou precisa ser feito em PHP? (lado do servidor)


Isso pode ser feito em sql . Uma maneira seria usar uma "tabela auxiliar" com apenas inteiros que você pode join seus dados para obter sua linha várias vezes e, em seguida, extrair apenas o n -th subelemento.

Tente isto:
-- 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;

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

Usei seus dados de exemplo que estão faltando alguns , , razão pela qual o resultado contém e. March 2 Feb 27 . Observe também que algumas subentradas estão vazias (já que meus dados de amostra incluem entradas vazias); você pode ou não querer filtrá-los. Sua tabela de inteiros obviamente terá que conter números pelo menos até o número máximo de elementos que você espera ter em qualquer uma de suas linhas (e se ela contiver um 0 ou números negativos, filtre-os no on -cláusula).

substring_index(str,delim,count) retorna a substring da string str antes de count ocorrências do delimitador delim . A instrução completa para subentry irá, para um número positivo, retornar o _int_1_10.id -th elemento ou, se a string tiver menos elementos, o último elemento.

O on -clause calcula assim o número de elementos (contando o número de , ) para evitar obter o último elemento várias vezes. Se sua string não contém nenhum elemento vazio (como o ,, nos meus dados de exemplo), você não precisa dessa parte, mas pode adicionar um elemento vazio para marcar o final da lista.

Você pode aplicar este código a todo o seu conjunto de resultados, por exemplo. usando
...
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 ...

Vai funcionar, mas pode ser lento. Ele não pode usar um índice no space*_2_value -columns e terá que fazer muita junção e avaliação de strings. Você não pode fazer muito sobre isso, exceto normalizar seus dados.

Se for útil fazer isso em sql provavelmente dependerá do que você está fazendo com os dados. Se você for apenas exibi-lo em uma tabela html em uma página da Web, pode ser mais fácil e rápido apenas percorrer o array em php . Para classificar, filtrar ou join seu conjunto de resultados, provavelmente é muito mais fácil de implementar (e provavelmente mais rápido) em sql , talvez mesmo se você estiver usando-o em um framework. Se você for atualizar os valores, será muito mais fácil fazer em php , pois provavelmente será uma bagunça no sql (neste conjunto de resultados).