【MySQL】複数レコードのカラム内容を結合して取得する


前提

複数の行にある同じ列の内容をSQLでまとめて取得したいとき。
例えば、ブログアプリの記事一覧にコメントした人全員の名前を載せたいとする。

参考イメージ「Aさん〜」の部分など

参考情報:列をまとめる CONCAT関数

MySQLで列の内容をまとめるときには、CONCAT関数が使える

-- 準備
CREATE TABLE User(id integer, last_name varchar(100), first_name varchar(100));
INSERT INTO User(id, last_name, first_name) VALUES(1, "田中","太郎"),(2, "鈴木","次郎"),(3, "遠藤","三郎");
-- 名前をくっつける
SELECT id, CONCAT(last_name, first_name) FROM User;
-- => 1 田中太郎 など

ちなみに数値型と文字列型でも結合してくれる

SELECT CONCAT(id, first_name) FROM User;
-- 1太郎

本題:集計して列をまとめる GROUP_CONCAT関数

今回の場合は、複数の行にまたがっている列を1つにまとめたいので、CONCAT関数に似ているGROUP_CONCAT関数を使う。
GROUP_CONCAT関数はGROUPBYと一緒に用いる集計関数で、列を集計する際にどのように集計するかを指定している。

集計関数のイメージ

GROUP_CONCAT関数の場合は 「文字列として結合してくれる」

-- 準備
CREATE TABLE Student(id integer, class varchar(10), name varchar(100));
INSERT INTO Student(id, class, name) VALUES(1, "A", "田中"),(2, "A", "鈴木"),(3, "A", "遠藤");

-- 名前をくっつける
SELECT class, GROUP_CONCAT(name) FROM Student GROUP BY class;
-- class	GROUP_CONCAT(name)
-- A	田中,鈴木,遠藤

カンマになっているセパレーターは指定することができる

SELECT class, GROUP_CONCAT(name SEPARATOR '-') FROM Student GROUP BY class;
-- A	田中-鈴木-遠藤

並び順を指定することもできる

SELECT class, GROUP_CONCAT(name ORDER BY id DESC) FROM Student GROUP BY class;
-- A	遠藤,鈴木,田中

条件式などを組み込むことも可能

-- 名前をくっつける
SELECT class, GROUP_CONCAT(CASE WHEN NAME = "鈴木" THEN "◯" ELSE "×" END) FROM Student GROUP BY class;
-- A	×,◯,×

前提としている場合以外でも色々と使えそうなので、ぜひ活用していきたい。

参考

12.19.1 GROUP BY (集約) 関数
MySQLの文字列結合にはCONCAT。GROUP_CONCATとGROUP BYで複数データ集約