MySQL:在列中拆分值以获取多行

Spa*_*tus 7 mysql select

我在表中有一些数据,如下所示:

product_id      | categories
----------------+-------------
10              | 9,12
11              | 8
12              | 11,18,5
Run Code Online (Sandbox Code Playgroud)

我想要一个会产生这个输出的选择语句:

product_id      | category_id
----------------+-------------
10              | 9
10              | 12
11              | 8
12              | 11
12              | 18
12              | 5
Run Code Online (Sandbox Code Playgroud)

我不知道如何表达这种情况才能用谷歌搜索它。

Rol*_*DBA 5

您正在寻找的是使用 GROUP_CONCAT 的 GROUP BY 聚合查询的逆。如果您愿意将结果存储在临时表中,那么我就知道了。

首先,这里是在一个名为的表中使用示例数据的代码prod和一个名为的临时表,prodcat用于保存您正在寻找的结果。

use test
drop table if exists prod;
drop table if exists prodcat;
create table prod
(
  product_id int not null,
  categories varchar(255)
) engine=MyISAM;
create table prodcat
(
  product_id int not null,
  cat  int not null
) engine=MyISAM;
insert into prod values
(10,'9,12'),(11,'8'),(12,'11,18,5');
select * from prod;
Run Code Online (Sandbox Code Playgroud)

这里加载了

mysql> use test
Database changed
mysql> drop table if exists prod;
Query OK, 0 rows affected (0.00 sec)

mysql> drop table if exists prodcat;
Query OK, 0 rows affected (0.00 sec)

mysql> create table prod
    -> (
    ->   product_id int not null,
    ->   categories varchar(255)
    -> ) engine=MyISAM;
Query OK, 0 rows affected (0.07 sec)

mysql> create table prodcat
    -> (
    ->   product_id int not null,
    ->   cat  int not null
    -> ) engine=MyISAM;
Query OK, 0 rows affected (0.06 sec)

mysql> insert into prod values
    -> (10,'9,12'),(11,'8'),(12,'11,18,5');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from prod;
+------------+------------+
| product_id | categories |
+------------+------------+
|         10 | 9,12       |
|         11 | 8          |
|         12 | 11,18,5    |
+------------+------------+
3 rows in set (0.00 sec)

mysql>
Run Code Online (Sandbox Code Playgroud)

好的,您需要查询将每个 product_id 与每个类别放在一起。这里是:

select concat('insert into prodcat select ',product_id,',cat from (select NULL cat union select ',
replace(categories,',',' union select '),') A where cat IS NOT NULL;') ProdCatQueries from prod;
Run Code Online (Sandbox Code Playgroud)

这里执行

mysql> select concat('insert into prodcat select ',product_id,',cat from (select NULL cat union select ',
    -> replace(categories,',',' union select '),') A where cat IS NOT NULL;') ProdCatQueries from prod;
+----------------------------------------------------------------------------------------------------------------------------------+
| ProdCatQueries                                                                                                                   |
+----------------------------------------------------------------------------------------------------------------------------------+
| insert into prodcat select 10,cat from (select NULL cat union select 9 union select 12) A where cat IS NOT NULL;                 |
| insert into prodcat select 11,cat from (select NULL cat union select 8) A where cat IS NOT NULL;                                 |
| insert into prodcat select 12,cat from (select NULL cat union select 11 union select 18 union select 5) A where cat IS NOT NULL; |
+----------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql>
Run Code Online (Sandbox Code Playgroud)

让我手动运行每一行

mysql> insert into prodcat select 10,cat from (select NULL cat union select 9 union select 12) A where cat IS NOT NULL;
Query OK, 2 rows affected (0.07 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into prodcat select 11,cat from (select NULL cat union select 8) A where cat IS NOT NULL;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into prodcat select 12,cat from (select NULL cat union select 11 union select 18 union select 5) A where cat IS NOT NULL;
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>
Run Code Online (Sandbox Code Playgroud)

好的,不错。查询工作。prodcat 表是否正确填充?

mysql> select * from prodcat;
+------------+-----+
| product_id | cat |
+------------+-----+
|         10 |   9 |
|         10 |  12 |
|         11 |   8 |
|         12 |  11 |
|         12 |  18 |
|         12 |   5 |
+------------+-----+
6 rows in set (0.00 sec)

mysql>
Run Code Online (Sandbox Code Playgroud)

太好了。它有数据。

老实说,我认为 SQL Server 可以在没有手工临时表的情况下在单个数据透视查询中执行所有这些操作。

我本可以将它提升到另一个级别并将所有查询连接到一个查询中,但是 SQL 会非常长。如果您的实际查询有 1000 行,单个 MySQL 将不实用。

您可以将 3 个 INSERT 查询回显到文本文件并将其作为脚本执行,而不是手动运行 3 个 INSERT 查询。然后,您有一个表格,其中包含单独编写的产品和类别组合。