mysql csv format pivot group-concat

¿Qué es lo opuesto a GROUP_CONCAT en MySQL?



csv format (4)

Parece que estoy en contra de este problema mucho, donde tengo datos con el formato siguiente:

+----+----------------------+ | id | colors | +----+----------------------+ | 1 | Red,Green,Blue | | 2 | Orangered,Periwinkle | +----+----------------------+

pero quiero formatearlo así:

+----+------------+ | id | colors | +----+------------+ | 1 | Red | | 1 | Green | | 1 | Blue | | 2 | Orangered | | 2 | Periwinkle | +----+------------+

¿Existe una forma correcta de hacer esto? ¿Cómo se llama este tipo de operación?


¡Esto me ahorró muchas horas! Yendo un paso más allá: en una implementación típica, probablemente existiría una tabla que enumera los colores frente a una clave de identidad, color_list . Se puede agregar un nuevo color a la implementación sin tener que modificar la consulta y se puede evitar la cláusula de union potencialmente interminable cambiando la consulta a esto:

SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(colors, '','', n.digit+1), '','', -1) color FROM colors INNER JOIN (select id as digit from color_list) n ON LENGTH(REPLACE(colors, '','' , '''')) <= LENGTH(colors)-n.digit ORDER BY id, n.digit;

Sin embargo, es importante que los Id en la tabla color_list permanezcan secuenciales.


Creo que es lo que necesita (procedimiento almacenado): Mysql divide la cadena de columna en filas

DELIMITER $$ DROP PROCEDURE IF EXISTS explode_table $$ CREATE PROCEDURE explode_table(bound VARCHAR(255)) BEGIN DECLARE id INT DEFAULT 0; DECLARE value TEXT; DECLARE occurance INT DEFAULT 0; DECLARE i INT DEFAULT 0; DECLARE splitted_value INT; DECLARE done INT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT table1.id, table1.value FROM table1 WHERE table1.value != ''''; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; DROP TEMPORARY TABLE IF EXISTS table2; CREATE TEMPORARY TABLE table2( `id` INT NOT NULL, `value` VARCHAR(255) NOT NULL ) ENGINE=Memory; OPEN cur1; read_loop: LOOP FETCH cur1 INTO id, value; IF done THEN LEAVE read_loop; END IF; SET occurance = (SELECT LENGTH(value) - LENGTH(REPLACE(value, bound, '''')) +1); SET i=1; WHILE i <= occurance DO SET splitted_value = (SELECT REPLACE(SUBSTRING(SUBSTRING_INDEX(value, bound, i), LENGTH(SUBSTRING_INDEX(value, bound, i - 1)) + 1), '','', '''')); INSERT INTO table2 VALUES (id, splitted_value); SET i = i + 1; END WHILE; END LOOP; SELECT * FROM table2; CLOSE cur1; END; $$


Puede usar una consulta como esta:

SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(colors, '','', n.digit+1), '','', -1) color FROM colors INNER JOIN (SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) n ON LENGTH(REPLACE(colors, '','' , '''')) <= LENGTH(colors)-n.digit ORDER BY id, n.digit

Por favor, mira el violín here . Tenga en cuenta que esta consulta admitirá hasta 4 colores por cada fila, debe actualizar su subconsulta para devolver más de 4 números (o debe usar una tabla que contenga 10 o 100 números).


observe que esto se puede hacer sin crear una tabla temporal

select id, substring_index(substring_index(genre, '','', n), '','', -1) as genre from my_table join (SELECT @row := @row + 1 as n FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (SELECT @row:=0) r) as numbers on char_length(genre) - char_length(replace(genre, '','', '''')) >= n - 1