VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
COUNT はグループに何行あるかを教えてくれます。GROUP_CONCAT は、それらの値を
1 つの文字列に連結して、何があったかを教えてくれます。詳細を数に減らすのではなく、
詳細を保つ集計関数です。
始める前に mysql -u root -p sakila でクライアントを開いてください。
GROUP_CONCAT の仕組み
GROUPING_COLUMN をグループを定める列に、TABLE_NAME をテーブルに、
COLUMN_NAME を連結する列に、SEPARATOR_TEXT を値の間に入れるものに置き換え
ます。ORDER BY と SEPARATOR はどちらも省略でき、周りのクエリではなく括弧の
中に置きます。
SEPARATOR がないと、値は空白なしのカンマで連結されます。ORDER BY がないと、
値は特定の順序なしに並びます。
例
- 各グループの値を連結する
NC-17 の映画はなく、WHERE がグループ化の前に
その行を取り除いたからです。行が残らなかったグループは現れません。
- 重複を落とす
括弧の中の DISTINCT は、各グループ内の重複する値を取り除きます。
DISTINCT がなければ、各文字列はグループ内の映画ごとに料金を 1 つずつ、178 から
223 個保持し、長いほうの 2 つは次のセクションで扱う制限にぶつかります。これは
デフォルトの区切り文字でもあります。カンマだけで、他には何もありません。
結果は group_concat_max_len バイトで切り捨てられる
これが罠です。サーバーは長くなりすぎたGROUP_CONCAT の結果を切り捨て、
エラーを出しません。制限は設定なので、下の数値は MySQL の性質ではなくこの
サーバーのものであり、文字数ではなくバイト数を数えます。
SHOW WARNINGS が何が失われた
かを教えてくれます。Warning 1260 Row 65 was cut by GROUP_CONCAT() です。
文字列は 1,000 本のうち 64 本のタイトルを丸ごと保持し、65 本目の途中で止まって
います。
GROUP_CONCAT の後に自分で SHOW WARNINGS を実行すると、同じメッセージが
見られます。
SET SESSION group_concat_max_len = 100000; は、接続の残りの間だけ制限を引き
上げ、再接続すると元に戻ります。制限はバイト数を数えるため、ASCII 以外の
テキストは数値が示すより早く切られます。utf8mb4 では 1 文字が最大 4 バイトを
取り得ます。
長さが group_concat_max_len とちょうど等しい結果は、確認するまで切り捨てられた
ものとして扱い、フッターの警告数に注意してください。
まとめ
- グループ内の値を 1 つの文字列に連結するには
GROUP_CONCATを使います。 ORDER BY、SEPARATOR、およびDISTINCTは括弧の中に置きます。- 区切り文字を指定しないときは、空白なしのカンマになると考えてください。
group_concat_max_lenバイトで切り捨てられ、エラーではなく警告が出ると考えてください。- 長さが制限とちょうど等しいときは、常に切り捨てを疑います。
関連項目
- 集計関数 — 数を返す集計関数
- GROUP BY — この関数が連結するグループを作る
- MySQL の文字列関数 — その後で文字列を加工する
- MySQL の GROUP BY のパフォーマンス — 大規模にこれらの文字列を作るコスト