"Reverse GROUP_CONCAT" in MySQL?

I seem to be very strongly opposed to this problem, where I have data formatted as follows:

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

but I want it to be formatted as follows:

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

Is there a good way to do this? What is the name of this operation?

+18
mysql format
Jun 25 '13 at 22:30
source share
4 answers

I think this is what you need (stored procedure): Mysql splits a column row into rows

 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; $$ 
+7
Jun 25 '13 at 22:45
source share
β€” -

You can use this query:

 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 

See the fiddle here. Note that this query supports up to 4 colors for each row, you must update your subquery to return more than 4 numbers (or you should use a table containing 10 or 100 numbers).

+8
Jun 25 '13 at 22:36
source share

It saved me many hours! Let's take one more step: with a typical implementation, there will probably be a table that lists the colors against the identification key, color_list . A new color can be added to the implementation without having to change the request, and a potentially infinite union -clause can be avoided altogether by changing the request to this:

 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; 

It is important that the identifiers in the color_list table remain consistent.

0
Jun 19 '15 at 14:19
source share

Please note that this can be done without creating a temporary table.

 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 
0
Mar 01 '16 at 17:08
source share



All Articles