※この記事にはアフィリエイト広告(プロモーション)が含まれます。
GROUP_CONCAT は複数行の値をカンマ区切りの1つの文字列にまとめる集約関数です。結果の上限は既定で 1024 バイトです。超えた分は、SELECT では警告が出るだけで切り捨てられます。この記事の出力は MySQL 8.4.11(Ubuntu 26.04)で採りました。
まず見る(結論)
SELECT @@group_concat_max_len; -- 既定 1024(バイト)
SET SESSION group_concat_max_len = 1000000; -- この接続だけ広げる
- SELECT で切れたときは警告
1260 Row 114 was cut by GROUP_CONCAT()だけで、結果は返る INSERT ... SELECT・CREATE TABLE ... AS SELECT・UPDATEの中で切れるとERROR 1260 (HY000)で失敗する(既定の sql_mode)
基本の書き方
SELECT dept, GROUP_CONCAT(name ORDER BY id SEPARATOR ',') AS names FROM emp GROUP BY dept;
+--------+------------------+
| dept | names |
+--------+------------------+
| 営業 | 佐藤,鈴木 |
| 開発 | 高橋,田中 | -- name が NULL の行は含まれない
+--------+------------------+
| 書き方 | 結果 |
|---|---|
GROUP_CONCAT(DISTINCT dept ORDER BY dept) |
営業,開発 |
GROUP_CONCAT(id) |
1,2,3,4,5(数値もそのまま使える) |
GROUP_CONCAT(COALESCE(name, '(null)') ORDER BY id) |
佐藤,鈴木,高橋,(null),田中 |
| 対象が0行 | 空文字ではなく NULL |
区切り文字の既定はカンマです。ORDER BY を書かないと並び順は保証されません。
1024 バイトで切れる
8文字のコードを500行まとめました。切れなければ 4499 バイトになる結果です。
SELECT LENGTH(GROUP_CONCAT(code)) AS len, RIGHT(GROUP_CONCAT(code ORDER BY id), 20) AS tail_ FROM codes;
SHOW WARNINGS;
+------+----------------------+
| len | tail_ |
+------+----------------------+
| 1024 | 112,CCCCC113,CCCCC11 |
+------+----------------------+
| Warning | 1260 | Row 114 was cut by GROUP_CONCAT() |
114行目の途中で切れ、残りの386行は入っていません。クエリ自体は成功するので、アプリケーション側で警告を見ていないと切れたことに気づけません。
上限はバイト数です。東京1 のような日本語(utf8mb4)でまとめると、LENGTH は 1022 バイト、CHAR_LENGTH は 570 文字でした。文字の途中では切れず、最後は 東京113, の区切り文字で終わっていました。
INSERT・UPDATE の中ではエラーになる
INSERT INTO r SELECT GROUP_CONCAT(code) FROM codes;
ERROR 1260 (HY000): Row 114 was cut by GROUP_CONCAT()
CREATE TABLE ... AS SELECT と、副問い合わせで GROUP_CONCAT を使う UPDATE でも同じエラーになりました。
既定の sql_mode には STRICT_TRANS_TABLES が含まれるため、データを書き込む文では警告がエラーに変わります。
group_concat_max_len を変える
SET SESSION group_concat_max_len = 1000000;
SELECT LENGTH(GROUP_CONCAT(code)) FROM codes; -- 4499、警告なし
SET GLOBAL group_concat_max_len = 1000000;
SELECT @@SESSION.group_concat_max_len, @@GLOBAL.group_concat_max_len;
1024 | 1000000 -- 今の接続は変わらない
SET GLOBAL は、その後に開いた接続から効きます。再起動後も残すなら SET PERSIST か設定ファイルに書きます(スロークエリログの記事 で SET PERSIST を使っています)。
| 設定値 | 結果 |
|---|---|
4 |
GROUP_CONCAT(id) が 1,2, |
0 |
エラーにならず、最小値の 4 になった |
18446744073709551615 |
そのまま設定できた |
JSON_ARRAYAGG(code) は group_concat_max_len の影響を受けず、1024 のままでも 6000 バイトの結果を警告なしで返しました。