2013-06-25 238 views
20

我似乎來對這個問題有很多,在這裏我的影片格式如下數據:「Reverse GROUP_CONCAT」in MySQL?

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

但我想它的格式是這樣的:

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

有沒有做一個好辦法這個?這種手術甚至叫什麼?

+1

該操作被稱爲旋轉/ unpivoting – nothrow

+0

真棒做,謝謝 –

回答

7

我認爲這是你需要什麼(存儲過程):Mysql split column string 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; $$ 
+0

太棒了,那就是我一直在尋找 –

+0

棒極了!你是個男子漢!!! :D –

+1

@ kmas,「stocked procedure」是什麼意思? – Pacerier

10

你可以使用這樣的查詢:

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 

請參閱小提琴here。請注意,該查詢每行最多支持4種顏色,應更新子查詢以返回4個以上的數字(或者應使用包含10或100個數字的表格)。

+0

這並不完全符合我要找的,我更想找每個ID可以處理N行的東西。謝謝:) –

+0

@JasonHamje如果你需要使用查詢而不是存儲過程,那麼沒有其他的方法:) – fthiella

+0

哎呀,謝謝 –

0

這救了我很多時間!更進一步:在一個典型的實現中,所有可能的情況都會是一張桌面,其中列舉了與身份驗證密鑰color_list相對應的顏色。新的色彩可以被添加到實施,而無需修改查詢,並可以通過改變查詢到這個完全避免潛在的無盡union -clause:

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; 

重要的是,這些ID表color_list保持順序,但是。

0

通知這可以在不創建臨時表

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

也可以添加計數和分組,如果你想 –