MySQLにはGROUP_CONCATという、グループ内の複数の行の値を連結して一つの文字列に変換できる便利な機能があります。
その使い方と注意点について記載していきます
以下のように使用します。この例ではグループに所属するユーザーの名前を連結して取得するイメージです。
SELECT groups.name, GROUP_CONCAT(users.name) AS user_names
FROM groups
JOIN users ON users.group_id = groups.id
GROUP BY groups.name;
デフォルトではカンマ区切りで取得します。下記のような取得結果になります。
groups.name | user_names |
---|---|
営業グループ | 営業一郎,営業二郎,営業三郎 |
開発グループ | 開発春子,開発夏子,開発秋子,開発冬子 |
SEPARATORオプションを使用することで、カンマ以外の任意の区切り文字を使用することが可能です。
以下の例では /
区切りで文字列を連結しています。
SELECT groups.name, GROUP_CONCAT(users.name SEPARATOR '/') AS user_names
FROM groups
JOIN users ON users.group_id = groups.id
GROUP BY groups.name;
以下のような出力結果になるイメージです。
groups.name | user_names |
---|---|
営業グループ | 営業一郎/営業二郎/営業三郎 |
GROUP_COCATの引数にカンマ区切りでカラム名を追加していくことで、それらのカラムの内容を連結して出力することが可能です。
以下の例ではusers.idとusers.nameを :
で繋げています。
SELECT groups.name, GROUP_CONCAT(users.id, ":", users.name SEPARATOR '/') AS user_names
FROM groups
JOIN users ON users.group_id = groups.id
GROUP BY groups.name;
以下のような出力結果になるイメージです。
groups.name | user_names |
---|---|
営業グループ | 1:営業一郎/2:営業二郎/3:営業三郎 |
GROUP_CONCAT内では order by
句が使用して、並び替え後に連結することも可能です。
以下の例ではusers.idの降順で並び替えを行った後、連結しています。
SELECT groups.name, GROUP_CONCAT(users.id, ":", users.name ORDER BY users.id DESC SEPARATOR '/') AS user_names
FROM groups
JOIN users ON users.group_id = groups.id
GROUP BY groups.name;
以下のような出力結果になるイメージです。
groups.name | user_names |
---|---|
営業グループ | 3:営業三郎/2:営業二郎/1:営業一郎 |
使い方の説明は以上になります。
MySQLのGROUP_CONCATですが、連結して取得可能な文字列のデフォルトの長さが1024文字であることに注意が必要です。
1024文字を超える場合は、それ以降の文字列が切り捨てられてしまうため、意図した値が取得できない可能性があります。
以下のsqlを実行することで確認可能です
SHOW VARIABLES LIKE 'group_concat_max_len';
Valiable_name | Value |
---|---|
group_concat_max_len | 1024 |
下記のようにgroup_concat_max_lenのサイズを大きくすることも可能ですが、DBサーバーへの負荷が高まることを考えると、採用は慎重になるべきでしょう。
set session group_concat_max_len=10000;
以上です。
GROUP_CONCATは大変便利な関数ですが、最大長について気をつけながら使い所を見極めていきたいです。
富山在住のプログラマー。
フルリモートで働いています。
Categories
AWS
Cloudflare
Docker
Github
go
html
JavaScript
microCMS
MySQL
Monthly Archives
2024/12 (1)
2024/11 (3)
2024/10 (1)
2024/09 (3)
2024/08 (7)
2024/07 (7)
2024/06 (4)
2024/05 (5)
2024/04 (6)