MySQLでGROUP BY時にすべての値を連結して取得 (GROUP_CONCAT)

MySQL

この記事は最終更新日から1年以上が経過しています。

はじめに

1対多の関係を持ったテーブル同士をJOINしてGROUP BYして取得したときに、
多の方のデータをどうにかしてすべて取得したかったときの話です。

どんなテーブルだったか

わかりやすいように簡潔なテーブルにします。

userテーブル
ユーザ情報のテーブル

user_artist_relationテーブル
ユーザとアーティストを紐付けるテーブル

userテーブル対 user_artist_relationテーブルが、1対多の関係になっています。

結合して取得

このときは、ユーザを基準にページネーションしなければならなかったので、
ユーザごとにグループ化して取得。

このようにしてしまうと当然ですが、先頭の artist_idしか取得できません。

また、MySQL 5.7.5からはSQLモードにデフォルトでONLY_FULL_GROUP_BYが設定されているのでエラーになります。

ならばGROUP BYせずに以下のように全部取得したらいいのでは、、、

しかしよくよく考えてみると、今回はユーザ基準でページネーションしなければならなかったので、当然全件数がおかしくなってしまいますし、LIMIT,OFFSETをつけると変なところで切れてしまうことに気づきました。orz
そこでなんとかならないかと調べてみると、、、

GROUP_CONCAT関数

選ばれたのはGROUP_CONCAT関数でした。
GROUP BYしたときに、任意のカラムのデータを連結して文字列とすることで、データを1レコードにまとめることができます。
以下のようにして使います。

このクエリを投げてみると

artist_idのすべてのデータが連結した形で取得することができました。
これで今回の問題を解決することができました。

他にも

今回はそんなに関係ないですがDISTINCTで重複データを削除できます。
また、連結する順序をORDER BYで指定できたり、区切り文字を指定できたりします。

まとめ

GROUP_CONCAT関数はとても便利でした。
但し、大規模データを扱う場合はSQLの実行計画を確認する必要があります。

MySQL