ERROR: column "c.name" must appear in the GROUP BY clause or be used in an aggregate function は、GROUP BY で集計するときに、グループごとに1つに決まらない列を SELECT・ORDER BY・HAVING に書いたときのエラーです。 エラー文の "c.name" が問題の列で、^ がその位置を指します。

エラー文のとおり、その列を GROUP BY に入れるか、集計関数で包むかですが、どちらが正しいかは「何を出したいか」で決まります。

やりたいこと 書き方
顧客ごとに集計して、顧客の名前も出す 主キー(c.id)で GROUP BY(名前は GROUP BY に書かなくてよい)
グループごとの最新の1行 DISTINCT ON または ROW_NUMBER()
グループの値を並べる string_agg(DISTINCT 列, ',')
グループの合計を各行に添える ウィンドウ関数 SUM(...) OVER (PARTITION BY ...)

確認環境:PostgreSQL 16.15(確認日 2026年10月11日)。MySQL のエラー(1055)の記事と同じデータで再現しました。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「must appear in the GROUP BY clauseの直し方」

再現

customers(主キー id)     orders2
id  name  pref             id  customer_id  amount  ordered_at
1   佐藤  東京             1   1            1000    2026-10-01
2   鈴木  大阪             2   1            3000    2026-10-05
3   高橋  東京             3   2            2000    2026-10-02
                           4   3            500     2026-10-03
                           5   3            800     2026-10-09
SELECT pref, name, SUM(o.amount) FROM customers c JOIN orders2 o ON o.customer_id = c.id GROUP BY pref;
ERROR:  column "c.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT pref, name, SUM(o.amount) FROM customers c JOIN order...
                     ^

「東京」には佐藤と高橋がいるので、name を1つに決められません。MySQL のように「どれか1つ」を返す設定はなく、PostgreSQL では常にエラーになります。

直し方1:主キーで GROUP BY する

SELECT c.id, c.name, c.pref, SUM(o.amount) AS total
FROM customers c JOIN orders2 o ON o.customer_id = c.id
GROUP BY c.id;
 id | name | pref | total
----+------+------+-------
  1 | 佐藤 | 東京 |  4000
  2 | 鈴木 | 大阪 |  2000
  3 | 高橋 | 東京 |  1300

GROUP BY にテーブルの主キーを入れると、同じテーブルのほかの列(name・pref)は書かなくても通りました。 主キーが決まれば、ほかの列も1つに決まるためです(PostgreSQL 公式ドキュメントの「関数従属」)。

主キーが無いテーブルでは通らない

(同じデータで、id が主キーではないテーブル customers_nopk)
SELECT c.id, c.name, SUM(o.amount) FROM customers_nopk c JOIN ... GROUP BY c.id;
ERROR:  column "c.name" must appear in the GROUP BY clause or be used in an aggregate function

id の値が実際には重複していなくても、主キーが定義されていないとエラーになりました。 公式ドキュメントでも、関数従属を認めるのは「GROUP BY に、そのテーブルの主キーが含まれるとき」だけとされています。UNIQUE 制約だけの列も、この扱いの対象外です。その場合は、GROUP BY c.id, c.name のように列を並べます。

直し方2:グループごとの最新の1行(DISTINCT ON)

SELECT customer_id, MAX(ordered_at), amount FROM orders2 GROUP BY customer_id;
ERROR:  column "orders2.amount" must appear in the GROUP BY clause or be used in an aggregate function

「最新の注文の金額」は、GROUP BY では書けません。PostgreSQL の DISTINCT ON を使います。

SELECT DISTINCT ON (customer_id) customer_id, ordered_at, amount
FROM orders2
ORDER BY customer_id, ordered_at DESC;
 customer_id |     ordered_at      | amount
-------------+---------------------+--------
           1 | 2026-10-05 00:00:00 |   3000
           2 | 2026-10-02 00:00:00 |   2000
           3 | 2026-10-09 00:00:00 |    800

DISTINCT ON (列) は、その列が同じ行のうち、ORDER BY で先頭に来た1行だけを残します。 公式ドキュメントのとおり、DISTINCT ON の列を ORDER BY の先頭に書き、その後ろに「どの行を先にするか」(ordered_at DESC)を書きます。ORDER BY が無いと、どの行が残るかは決まりません。

ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY ordered_at DESC) で番号を付けて 1 番を取る方法でも、同じ結果になります(MySQL など他の DB でも使える書き方)。

直し方3:グループの値を並べる・どれか1つ

SELECT pref, string_agg(DISTINCT name, ',' ORDER BY name) AS names, SUM(o.amount) AS total
FROM customers c JOIN orders2 o ON o.customer_id = c.id
GROUP BY pref;
 pref |   names   | total
------+-----------+-------
 大阪 | 鈴木      |  2000
 東京 | 佐藤,高橋 |  5300

JOIN した結果を集計しているので、DISTINCT が無いと「佐藤,佐藤,高橋,高橋」のように注文の数だけ重なりました。

関数 結果
string_agg(DISTINCT 列, ',' ORDER BY 列) 値を並べる
any_value(列) どれか1つ(確認環境の PostgreSQL 16 で使えた)
max(列)・min(列) 最大・最小

any_value は MySQL の ANY_VALUE と同じく「どれか1つ」です。グループの中で値が同じだと分かっている列にだけ使います。

直し方4:合計を各行に添える(ウィンドウ関数)

「顧客ごとの合計」と「都道府県ごとの合計」を同じ行に出したいときは、GROUP BY ではなくウィンドウ関数を使います。

SELECT c.name, c.pref, t.total,
       SUM(t.total) OVER (PARTITION BY c.pref) AS pref_total
FROM customers c
JOIN (SELECT customer_id, SUM(amount) AS total FROM orders2 GROUP BY customer_id) t
  ON t.customer_id = c.id;
 name | pref | total | pref_total
------+------+-------+------------
 鈴木 | 大阪 |  2000 |       2000
 佐藤 | 東京 |  4000 |       5300
 高橋 | 東京 |  1300 |       5300

ORDER BY・HAVING でも出る

... GROUP BY pref ORDER BY c.name;
ERROR:  column "c.name" must appear in the GROUP BY clause or be used in an aggregate function

SELECT pref FROM customers GROUP BY pref HAVING name = '佐藤';
ERROR:  column "customers.name" must appear in the GROUP BY clause or be used in an aggregate function

HAVING の条件は、集計のあとに使われるので、集計していない列は使えません。行を絞る条件なら WHERE に書きます。

MySQL から移すときの違い

SQL MySQL 8.0(既定) MySQL(ONLY_FULL_GROUP_BY を外した) PostgreSQL
GROUP BY pref で name を SELECT ERROR 1055 どれか1つを返す エラー
主キーで GROUP BY、他の列を SELECT 通る 通る 通る
ANY_VALUE(name) 通る 通る any_value(name) で通る
最新の1行 ROW_NUMBER() 〃 DISTINCT ON または ROW_NUMBER()

MySQL で sql_mode を緩めて動かしていた SQL は、PostgreSQL ではそのままでは動きません。 移す前に、上の書き方に直します。

確認の手順(チェックリスト)

順番 確認すること 方法
1 問題の列 エラー文の column "..." と ^ の位置
2 何ごとに集計したいか 主キーごとなら、主キーで GROUP BY
3 主キーが定義されているか \d テーブル名。無ければ列を GROUP BY に並べる
4 最新の1行が欲しいか DISTINCT ON(ORDER BY の先頭をそろえる)
5 値を並べる・どれか1つ string_agg(DISTINCT ...)、any_value
6 HAVING に書いていないか 行の条件は WHERE に

よくある質問

Q. SQLSTATE は何ですか。 A. 42803(grouping_error)です。

Q. GROUP BY に列を全部書けば直りますか。 A. エラーは消えますが、グループの単位が変わり、結果の意味が変わります(都道府県ごとのつもりが、都道府県×名前ごとになる)。何ごとに集計したいかを決めてから直します。

まとめ

  • グループごとに1つに決まらない列を書いたエラー。PostgreSQL では常にエラー
  • 主キーで GROUP BY すれば、同じテーブルの他の列は書ける。主キーが無いと通らない
  • 最新の1行は DISTINCT ON(ORDER BY の先頭に同じ列)
  • 並べるなら string_agg(DISTINCT ...)。JOIN 後は重複に注意
  • HAVING の条件は集計後。行の条件は WHERE
  • MySQL で sql_mode を緩めていた SQL は、移す前に直す

参考・出典

確認日はいずれも 2026年10月11日です。

  • PostgreSQL 16 Documentation「SELECT」(GROUP BY Clause・DISTINCT Clause):https://www.postgresql.org/docs/16/sql-select.html
  • PostgreSQL 16 Documentation「Aggregate Functions」:https://www.postgresql.org/docs/16/functions-aggregate.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「must appear in the GROUP BY clauseの直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?