patternsqlMinor
MySQL: split value in column to get multiple rows
Viewed 0 times
rowscolumnvaluemysqlgetsplitmultiple
Problem
I have some data in a table like so:
I want a select statement that would produce this output:
I don't know how to phrase this scenario to be able to google it.
product_id | categories
----------------+-------------
10 | 9,12
11 | 8
12 | 11,18,5I want a select statement that would produce this output:
product_id | category_id
----------------+-------------
10 | 9
10 | 12
11 | 8
12 | 11
12 | 18
12 | 5I don't know how to phrase this scenario to be able to google it.
Solution
What you are looking for is the inverse of a GROUP BY aggregate query using the GROUP_CONCAT. If you are willing to store the results in a temp table, I got just the thing.
First, here is the code to use you sample data in a table called
Here it is loaded
OK, you need query to put together each product_id with each category. Here it is:
Here it is executed
Let me run each line by hand
OK, good. The queries work. Did the prodcat table populate properly?
OK Great. It has the data.
To be honest, I think SQL Server can perform all of this in a single pivot query without a handmade temp table.
I could have taken it to another level and concatenated all the queries into a single query, but the SQL would have been insanely long. If your actual query had 1000s of rows, a single MySQL would not have been practical.
Instead of running the 3 INSERT queries by hand, you could echo the 3 INSERT queries to a text file and execute it as a script. Then, you have a table with the products and categories combinations individually written.
First, here is the code to use you sample data in a table called
prod and a temp table called prodcat to hold the results you are looking for.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;Here it is loaded
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>OK, you need query to put together each product_id with each category. Here it is:
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;Here it is executed
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>Let me run each line by hand
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>OK, good. The queries work. Did the prodcat table populate properly?
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>OK Great. It has the data.
To be honest, I think SQL Server can perform all of this in a single pivot query without a handmade temp table.
I could have taken it to another level and concatenated all the queries into a single query, but the SQL would have been insanely long. If your actual query had 1000s of rows, a single MySQL would not have been practical.
Instead of running the 3 INSERT queries by hand, you could echo the 3 INSERT queries to a text file and execute it as a script. Then, you have a table with the products and categories combinations individually written.
Code Snippets
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;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>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;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>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>Context
StackExchange Database Administrators Q#57904, answer score: 5
Revisions (0)
No revisions yet.