MeWrite Docs

Column must appear in GROUP BY clause or aggregate function

SQLでGROUP BY句にカラムが含まれていない場合のエラー

概要

Column must appear in the GROUP BY clause or be used in an aggregate function は、GROUP BYを使用する際に、SELECT句のカラムがGROUP BY句に含まれていないか、集計関数で囲まれていない場合に発生するエラーです。

エラーメッセージ

PostgreSQL:

ERROR: column "table.column" must appear in the GROUP BY clause or be used in an aggregate function

MySQL (ONLY_FULL_GROUP_BY):

ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column

SQL Server:

Column 'table.column' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

原因

1
2
3
4
5
6
-- NG: nameがGROUP BYに含まれていない
SELECT department, name, COUNT(*)
FROM employees
GROUP BY department;

-- エラー: name must appear in GROUP BY clause

GROUP BYで集約すると、各グループに複数の行が存在する可能性があります。その中からどの name を選べばよいか不明なため、エラーになります。

解決策

1. GROUP BY句にカラムを追加

1
2
3
4
-- OK: nameもGROUP BYに追加
SELECT department, name, COUNT(*)
FROM employees
GROUP BY department, name;

2. 集計関数を使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- OK: MAX/MIN/ANY_VALUE等で1つの値を選択
SELECT department, MAX(name) AS sample_name, COUNT(*)
FROM employees
GROUP BY department;

-- OK: 名前をカンマ区切りで連結(PostgreSQL)
SELECT department, STRING_AGG(name, ', ') AS names, COUNT(*)
FROM employees
GROUP BY department;

-- OK: 名前をカンマ区切りで連結(MySQL)
SELECT department, GROUP_CONCAT(name) AS names, COUNT(*)
FROM employees
GROUP BY department;

3. SELECT句からカラムを削除

1
2
3
4
-- OK: 不要なカラムを削除
SELECT department, COUNT(*)
FROM employees
GROUP BY department;

4. サブクエリを使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
-- 各部署の最初の従業員を取得
SELECT e.department, e.name, dept_counts.cnt
FROM employees e
INNER JOIN (
    SELECT department, COUNT(*) AS cnt
    FROM employees
    GROUP BY department
) dept_counts ON e.department = dept_counts.department
WHERE e.id = (
    SELECT MIN(id) FROM employees e2
    WHERE e2.department = e.department
);

5. ウィンドウ関数を使用

1
2
3
-- 各部署の従業員と、その部署の人数を表示
SELECT department, name, COUNT(*) OVER (PARTITION BY department) AS dept_count
FROM employees;

MySQLの特殊な挙動

ONLY_FULL_GROUP_BY モード

1
2
3
4
5
-- MySQLでモードを確認
SELECT @@sql_mode;

-- ONLY_FULL_GROUP_BY が含まれていると厳格モード
-- 含まれていないと、非集約カラムは任意の値が返る(非推奨)
1
2
3
4
5
6
7
-- 一時的にモードを変更(非推奨)
SET sql_mode = '';

-- これで動くが、結果は不定
SELECT department, name, COUNT(*)
FROM employees
GROUP BY department;

ANY_VALUE関数(MySQL 5.7+)

1
2
3
4
-- どの値でもよい場合
SELECT department, ANY_VALUE(name) AS sample_name, COUNT(*)
FROM employees
GROUP BY department;

よくあるパターン

最新のレコードを取得

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- NG: 各ユーザーの最新注文を取得しようとして失敗
SELECT user_id, MAX(created_at), order_id
FROM orders
GROUP BY user_id;  -- order_idがエラー

-- OK: サブクエリで最新のorder_idを取得
SELECT o.*
FROM orders o
INNER JOIN (
    SELECT user_id, MAX(created_at) AS max_created
    FROM orders
    GROUP BY user_id
) latest ON o.user_id = latest.user_id
        AND o.created_at = latest.max_created;

-- OK: ウィンドウ関数を使用(PostgreSQL/MySQL 8.0+)
SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn
    FROM orders
) ranked
WHERE rn = 1;

集計と詳細の同時取得

1
2
3
4
5
6
7
8
9
-- 各商品の売上と、その商品の全注文を表示
SELECT
    p.product_id,
    p.name,
    o.order_id,
    o.quantity,
    SUM(o.quantity) OVER (PARTITION BY p.product_id) AS total_quantity
FROM products p
JOIN orders o ON p.product_id = o.product_id;

集計関数一覧

関数説明
COUNT(*)行数をカウント
COUNT(column)NULLでない値をカウント
SUM(column)合計
AVG(column)平均
MAX(column)最大値
MIN(column)最小値
STRING_AGG(column, delimiter)文字列連結(PostgreSQL)
GROUP_CONCAT(column)文字列連結(MySQL)
ARRAY_AGG(column)配列に集約(PostgreSQL)

関連エラー

関連エラー

SQL の他のエラー

最終更新: 2025-12-24