将逗号分隔的列值拆分(爆炸)到行

时间:2013-06-24 06:44:33

标签: mysql

描述

以下是表结构:

eligibility_table

ID     COURSE_ID     BRANCH_IDS
1      501           621,622,623
1      502
1      503           625
2      501           621
2      505           650
3      500

现在,我正在制作如下所述的新表结构,并通过eligibility_table插入course_table,branch_table。所以关注,我想要的最终输出

course_table

ID COURSE_ID
1  501
1  502
1  503
2  501
2  505
3  500

branch_table

ID BRANCH_ID
1  621
1  622
1  623
1  625
2  621
2  650

问题:

我正在努力为branch_table编写SQL QUERY。我想写一个像

这样的查询
INSERT INTO branch_table SELECT --- from eligibility_table --

2 个答案:

答案 0 :(得分:4)

更新您可以像这样使用SQL

INSERT INTO branch_table (id, branch_id)
SELECT e.id, SUBSTRING_INDEX(SUBSTRING_INDEX(e.branch_ids, ',', n.n), ',', -1) branch_id
  FROM eligibility_table e CROSS JOIN 
(
   SELECT a.N + b.N * 10 + 1 n
     FROM 
    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n
) n
 WHERE n.n <= 1 + (LENGTH(e.branch_ids) - LENGTH(REPLACE(e.branch_ids, ',', '')))
 ORDER BY id, branch_id
  • 在此特定情况下,使用UNION ALLCROSS JOIN,别名为n的子查询会动态生成1到100之间的数字序列(数字或计数表)。 有时在db 中有一个真正的计数表是很方便的。
  • 在外部选择最里面SUBSTRING_INDEX()获取列表中第n个元素的所有内容,并且在最后一个分隔符后有效地获取第n个元素本身的外部SUBSTRING_INDEX()提取最右边。
  • CROSS JOIN允许我们生成一组行,这是一个笛卡儿积(n中有100行,eligibility_table中有所有行)
  • WHERE子句中的条件过滤掉了结果集中所有不必要的行

注意:此查询最多可拆分100个分支ID。如果您需要更多或更少,可以通过编辑内部子查询来调整限制

结果在branch_table中:

| ID | BRANCH_ID |
------------------
|  1 |       621 |
|  1 |       622 |
|  1 |       623 |
|  1 |       625 |
|  2 |       621 |
|  2 |       650 |

这是 SQLFiddle 演示

答案 1 :(得分:3)

如果我是正确的,你正在改变你的数据库结构,所以它实际上是规范化的,这是一次性的事情,我建议你在代码中这样做。连接到数据库,读取旧表并插入新表。您也可以添加一些错误检查和异常处理!

只需使用您喜欢的语言,然后对该逗号分隔值执行标准split(),并在表格中插入这些值。如果它不起作用,您可以打印出错误的行,以便您可以手动修复这些问题。 (这将在sql中更难实现)