sql >> Base de Datos >  >> RDS >> Mysql

¿Se puede hacer esto en una consulta MySQL o es necesario hacerlo en PHP? (lado del servidor)

Esto se puede hacer en sql . Una forma sería usar una "tabla de ayuda" con solo números enteros a los que pueda join sus datos contra para obtener su fila varias veces y luego extraer solo el n -th subelemento.

Prueba esto:

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

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

Usé sus datos de muestra a los que les falta algo de , , por lo que el resultado contiene, p. March 2 Feb 27 . También tenga en cuenta que algunas subentradas están vacías (ya que mis datos de muestra incluyen entradas vacías); puede o no querer filtrarlos. Su tabla de enteros obviamente tendrá que contener números al menos hasta el número máximo de elementos que espera tener en cualquiera de sus filas (y si contiene un 0 o números negativos, filtrarlos en on -cláusula).

substring_index(str,delim,count) devuelve la subcadena de la cadena str antes de count ocurrencias del delimitador delim . La declaración completa para subentry devolverá, para un número positivo, el _int_1_10.id -ésimo elemento o, si la cadena tiene menos elementos, el último elemento.

El on -clause calcula así el número de elementos (contando el número de , ) para evitar obtener el último elemento varias veces. Si su cadena no contiene elementos vacíos (como ,, en mis datos de muestra), no necesita esa parte, pero podría agregar un elemento vacío para marcar el final de la lista.

Puede aplicar este código a todo su conjunto de resultados, p. 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 ...

Funcionará, pero podría ser lento. No puede usar un índice en el space*_2_value -columnas y tendrá que hacer muchas uniones y evaluación de cadenas. Sin embargo, no puede hacer mucho al respecto, excepto normalizar sus datos.

Si es útil hacer esto en sql probablemente dependerá de lo que esté haciendo con los datos. Si solo va a mostrarlo en una tabla html en una página web, podría ser más fácil y rápido recorrer la matriz en php . Para ordenar, filtrar o join su conjunto de resultados, probablemente sea mucho más fácil de implementar (y probablemente más rápido) en sql , tal vez incluso si lo está utilizando en un marco. Si va a actualizar los valores, será mucho más fácil hacerlo en php , ya que lo más probable es que sea un desastre en sql (en este conjunto de resultados).