文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

MySQLのgroup_concatで複数レコードを1行にまとめる

実は非常に有用で、この機能が実は欲しかった!と言う方が続出する機能なのですよね〜


f:id:treeapps:20180418131549p:plain

全然知らなかったのですが、mysqlでは複数レコードを1行にまとめる事ができます。
複数行をカンマ区切りにしたり、結構有効に使えそうです。

テーブル・データの準備

早速サンプルコードを。

テーブル

mysql> create table gc1(id int auto_increment, uid int, name varchar(30), primary key(id))engine=innodb charset=utf8mb4;
Query OK, 0 rows affected (0.06 sec)

mysql> desc gc1;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| uid   | int(11)     | YES  |     | NULL    |                |
| name  | varchar(30) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

データ

グルーピングしやすいデータを用意します。

mysql> insert into gc1 (uid, name) values (1,'cat'),(1,'dog'),(1,'bird'),(1,'cat'),(2,'mac mini'),(2,'mac book pro'),(2,'imac'),(2,'mac mini');
Query OK, 8 rows affected (0.02 sec)
Records: 8  Duplicates: 0  Warnings: 0

通常のselectとgroup_concatの差を見てみましょう。

実際に実行してみる

普通にselectしてみる

mysql> select * from gc1;
+----+------+--------------+
| id | uid  | name         |
+----+------+--------------+
|  1 |    1 | cat          |
|  2 |    1 | dog          |
|  3 |    1 | bird         |
|  4 |    1 | cat          |
|  5 |    2 | mac mini     |
|  6 |    2 | mac book pro |
|  7 |    2 | imac         |
|  8 |    2 | mac mini     |
+----+------+--------------+
8 rows in set (0.00 sec)

group_concatしてみる

mysql> select uid, group_concat(name separator ',') from gc1 where uid = 1;
+------+----------------------------------+
| name | group_concat(name separator ',') |
+------+----------------------------------+
| 1  | cat,dog,bird,cat                 |
+------+----------------------------------+
1 row in set (0.00 sec)

group_concat + distinct

なんと、group_concatした結果にdistinctできてしまいます。

mysql> select name, group_concat(distinct name order by name desc separator ',') from gc1 where uid = 1;
+------+--------------------------------------------------------------+
| name | group_concat(distinct name order by name desc separator ',') |
+------+--------------------------------------------------------------+
| cat  | dog,cat,bird                                                 |
+------+--------------------------------------------------------------+
1 row in set (0.00 sec)

group_concat + group by

更に、group_concatした結果をgroup byできてしまいます。

ついでに、group byしてユーザ毎にカンマ区切りで抽出できたりします。

mysql> select uid, group_concat(distinct name order by name desc separator ',') from gc1 group by uid;
+------+--------------------------------------------------------------+
| uid  | group_concat(distinct name order by name desc separator ',') |
+------+--------------------------------------------------------------+
|    1 | dog,cat,bird                                                 |
|    2 | mac mini,mac book pro,imac                                   |
+------+--------------------------------------------------------------+
2 rows in set (0.00 sec)

もっといじってみました。その2へ↓

実践ハイパフォーマンスMySQL 第3版

実践ハイパフォーマンスMySQL 第3版