【问题标题】:MySQL split multiple value into multiple rowsMySQL将多个值拆分为多行
【发布时间】:2018-09-03 08:50:31
【问题描述】:

在将多个值从多列拆分到另一列时,我需要帮助。下面是一个例子

CREATE TABLE split
(
    `Col_1`             VARCHAR(120),
    `Col_2`                 VARCHAR(50),
    `Col_3`                VARCHAR(20),
    `Col_4`                 VARCHAR(50)
);

Insert into split (Col_1,Col_2,Col_3,Col_4) values ('ABC','1','10',null);
Insert into split (Col_1,Col_2,Col_3,Col_4) values ('DEF','2,3','30,40',null);
Insert into split (Col_1,Col_2,Col_3,Col_4) values ('GHI','4,5','50','500,600,700');

select * from split;

+-------+-------+-------+-------------+
| Col_1 | Col_2 | Col_3 | Col_4       |
+-------+-------+-------+-------------+
| ABC   | 1     | 10    | NULL        |
| DEF   | 2,3   | 30,40 | NULL        |
| GHI   | 4,5   | 50    | 500,600,700 |
+-------+-------+-------+-------------+

我不是这方面的专家,但一直在玩,并设法将 col_2 拆分为多行,如下所示:

SELECT
  Col_1,Col_2,Col_3,Col_4,
  SUBSTRING_INDEX(SUBSTRING_INDEX(split.Col_2, ',', numbers.n), ',', -1) Col_2_NEW,
  SUBSTRING_INDEX(SUBSTRING_INDEX(split.Col_3, ',', numbers.n), ',', -1) Col_3_NEW,
  SUBSTRING_INDEX(SUBSTRING_INDEX(split.Col_4, ',', numbers.n), ',', -1) Col_4_NEW
FROM
  (SELECT 1 n UNION ALL SELECT 2
   UNION ALL SELECT 3 UNION ALL SELECT 4) numbers INNER JOIN split
  ON CHAR_LENGTH(split.Col_2) - CHAR_LENGTH(REPLACE(split.Col_2, ',', ''))>=numbers.n-1
ORDER BY Col_2, n;

+-------+-------+-------+-------------+-----------+-----------+-----------+
| Col_1 | Col_2 | Col_3 | Col_4       | Col_2_NEW | Col_3_NEW | Col_4_NEW |
+-------+-------+-------+-------------+-----------+-----------+-----------+
| ABC   | 1     | 10    | NULL        | 1         | 10        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 2         | 30        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 3         | 40        | NULL      |
| GHI   | 4,5   | 50    | 500,600,700 | 4         | 50        | 500       |
| GHI   | 4,5   | 50    | 500,600,700 | 5         | 50        | 600       |
+-------+-------+-------+-------------+-----------+-----------+-----------+

但是,我也想将 col_3 和 col_4 拆分为新的,所以它给了我下面的输出。

+-------+-------+-------+-------------+-----------+-----------+-----------+
| Col_1 | Col_2 | Col_3 | Col_4       | Col_2_NEW | Col_3_NEW | Col_4_NEW |
+-------+-------+-------+-------------+-----------+-----------+-----------+
| ABC   | 1     | 10    | NULL        | 1         | 10        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 2         | 30        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 2         | 40        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 3         | 30        | NULL      |
| DEF   | 2,3   | 30,40 | NULL        | 3         | 40        | NULL      |
| GHI   | 4,5   | 50    | 500,600,700 | 4         | 50        | 500       |
| GHI   | 4,5   | 50    | 500,600,700 | 4         | 50        | 600       |
| GHI   | 4,5   | 50    | 500,600,700 | 4         | 50        | 700       |
| GHI   | 4,5   | 50    | 500,600,700 | 5         | 50        | 500       |
| GHI   | 4,5   | 50    | 500,600,700 | 5         | 50        | 600       |
| GHI   | 4,5   | 50    | 500,600,700 | 5         | 50        | 700       |
+-------+-------+-------+-------------+-----------+-----------+-----------+

到目前为止,我已经进行了全面搜索,他们只将行拆分为一列,并且无法找到与我类似的问题。 也许缺少一些连接或一些联合,我不知道,因为我不擅长查询。 有人能帮我一下吗?不要求我阅读指南或手册:-)

提前致谢

【问题讨论】:

  • 谁能帮帮我?

标签: mysql


【解决方案1】:

你可以试试in this thread here的推荐之一。 类似于

的东西
 SELECT s.[Col_1], Split.a.value('.', 'VARCHAR(100)') AS String  
 FROM  (SELECT [Col_1], 
        CAST ('<M>' + REPLACE([Col_2], ',', '</M><M>') + '</M>' AS XML) AS String  
        FROM  split) AS s
 CROSS APPLY String.nodes ('/M') AS Split(a);

遍历您的列应该可以正常工作。

编辑:没看到这是 MySQL,抱歉。请参阅下面的有效解决方案。

以下代码应该适用于前两列。

1.) 创建表:

CREATE TABLE split(
    `Col_1`    VARCHAR(120),
    `Col_2`    VARCHAR(50),
    `Col_3`    VARCHAR(20),
    `Col_4`    VARCHAR(50)
);

INSERT INTO split (Col_1,Col_2,Col_3,Col_4) values ('ABC','1','10',null);
INSERT INTO split (Col_1,Col_2,Col_3,Col_4) values ('DEF','2,3','30,40',null);
INSERT INTO split (Col_1,Col_2,Col_3,Col_4) values ('GHI','4,5','50','500,600,700');

导致

SELECT * FROM split;

Col_1       Col_2       Col_3       Col_4
ABC         1           10          (null)
DEF         2,3         30,40       (null)
GHI         4,5         50          500,600,700

2.) 拆分 Col_2 中的字符串:

SELECT
  split.Col_1,
  SUBSTRING_INDEX(SUBSTRING_INDEX(split.Col_2, ',', numbers.n), ',', -1) Col_2,
  Col_3,
  Col_4
FROM
  (select 1 n UNION ALL
  select 2 UNION ALL select 3 UNION ALL
  select 4 UNION ALL select 5) numbers INNER JOIN split
  ON CHAR_LENGTH(split.Col_2)
 -CHAR_LENGTH(REPLACE(split.Col_2, ',', ''))>=numbers.n-1
ORDER BY Col_1, Col_2;

3.) 结果:

Col_1       Col_2       Col_3       Col_4
ABC         1           10          (null)
DEF         2           30,40       (null)
DEF         3           30,40       (null)
GHI         4           50          500,600,700
GHI         5           50          500,600,700

这是上面代码的 SQL fiddle:http://sqlfiddle.com/#!9/948fcb/4。 您应该能够从那里进行迭代。如果您需要更多指导,请评论此帖子。

重要提示:这适用于一列中最多 5 个逗号分隔的字符串。

解决方案的灵感来自 fthiella 对SQL split values to multiple rows 的回答。

【讨论】:

  • 谢谢米海。还没喝咖啡 - 将解决方案更改为 MySQL。
  • 谢谢@RomanAbashin。我遵循了 fthiella 示例本身的示例。但是你给我的查询只给我拆分到 Col_3,我如何拆分 Col_4。这一点,我能够用我给出的原始查询来实现,但不能再拆分一行。我想要的最终输出在我原来的问题中。再次感谢。
【解决方案2】:

只是想用最终查询来回答,这会根据需要为我提供所需的输出。 把它贴在这里,也许它会帮助别人。

SELECT distinct Col_1,Col_2,Col_3,Col_4,
 SUBSTRING_INDEX(SUBSTRING_INDEX(t.Col_2, ',', n.n), ',', -1) Col_2_New,
 SUBSTRING_INDEX(SUBSTRING_INDEX(t.Col_3, ',', n1.n), ',', -1) Col_3_New,
 SUBSTRING_INDEX(SUBSTRING_INDEX(t.Col_4, ',', n2.n), ',', -1) Col_4_New
  FROM split t 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 ) 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 ) b
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 ) c
    ORDER BY n 
   ) n,
  (
   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 ) 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 ) b
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 ) c
    ORDER BY n 
   ) n1,
  (
   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 ) 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 ) b
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 ) c
    ORDER BY n 
   ) n2
WHERE coalesce(n.n,'0') <= 1 + (LENGTH(coalesce(t.Col_2,'0')) - LENGTH(REPLACE(coalesce(t.Col_2,'0'), ',', '')))
 AND coalesce(n1.n,'0') <= 1 + (LENGTH(coalesce(t.Col_3,'0')) - LENGTH(REPLACE(coalesce(t.Col_3,'0'), ',', '')))
 AND coalesce(n2.n,'0') <= 1 + (LENGTH(coalesce(t.Col_4,'0')) - LENGTH(REPLACE(coalesce(t.Col_4,'0'), ',', '')))
 ORDER BY 1,2,3,4,5,6,7 ;

【讨论】:

    猜你喜欢
    • 2021-12-19
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2020-12-19
    • 2021-12-07
    相关资源
    最近更新 更多