1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQL初心者がつまずいた「GROUP BYとMAX()」の関係

1
Posted at

はじめに

業務でSQLを読んでいたとき、次のようなコードを見かけました。

SELECT
    customer_id,
    MAX(status) AS status
FROM orders
WHERE status = 1
GROUP BY customer_id;

最初に思ったのは、

WHERE句で status = 1 に絞り込んでいるのだから、MAX(status) の結果も必ず1になるのでは?

ということでした。

この段階で調べていくうちに、そもそも「GROUP BY」が何をしているのか。を十分理解できていなかったことに気付きました。

この記事では、SQLにまだ慣れていない方向けに、

  • GROUP BYとは何か
  • なぜエラーになるのか
  • なぜMAX()が必要なのか

を具体例を使いながら解説します。


まずはサンプルデータを見てみる

注文テーブル(orders)があるとします。

customer_id status
1 完了
2 完了
2 発送中
2 完了
3 完了
3 キャンセル

customer_id は顧客ID、
status は注文状況です。


GROUP BYとは何か

次はSQLを見てみます。

SELECT customer_id
FROM orders
GROUP BY customer_id;

結果はこうなります。

customer_id
1
2
3

GROUP BYは、

同じ値を持つ行をグループとしてまとめる

ための機能です。

イメージとしては次のようになります。

customer_id = 1
└ 完了

customer_id = 2
├ 完了
├ 発送中
└ 完了

customer_id = 3
├ 完了
└ キャンセル

customer_idごとにグループが作られている状態です。


なぜstatusをそのままSELECTできないの?

では次にこのSQLを見てみます。

SELECT
    customer_id,
    status
FROM orders
GROUP BY customer_id;

初心者の頃の私は、

customer_idでまとめているだけだから、statusも表示できるのでは?

と思っていました。

しかし、このSQLはエラーになります。


SQLはどのstatusを返せばいいか分からない

例えば customer_id = 2 のグループを見てみます。

customer_id = 2

完了
発送中
完了

ここでSQLは困ります。

customer_idは分かった

でもstatusはどれを返せばいいの?

完了?
発送中?
最後の完了?

どれが正しいのか判断できません。

そのためSQLは

どの値を返せばいいか分からないのでエラーにします

という動きをします。


GROUP BYにはルールがある

GROUP BYを使う場合、

SELECT句には次のどちらかしか書けません。

① GROUP BYで指定した列

SELECT customer_id
FROM orders
GROUP BY customer_id;

② 集計関数で囲んだ列

SELECT
    customer_id,
    MAX(status)
FROM orders
GROUP BY customer_id;

代表的な集計関数には次のようなものがあります。

関数 意味
MAX() 最大値
MIN() 最小値
SUM() 合計
AVG() 平均
COUNT() 件数

MAX()を使うとエラーにならない理由

次のSQLを見てみます。

SELECT
    customer_id,
    MAX(score)
FROM scores
GROUP BY customer_id;

データが次のようになっていた場合、

customer_id score
2 10
2 30
2 20

結果はこうなります。

customer_id MAX(score)
2 30

今回はSQLに

一番大きい値を返してください

という明確な指示を出しています。

そのためSQLは迷わず結果を返せます。


では今回のSQLでは何が起きている?

今回のSQLはこちらでした。

SELECT
    customer_id,
    MAX(status)
FROM orders
WHERE status = 1
GROUP BY customer_id;

まずWHERE句が実行されます。

WHERE status = 1

によって、statusが1のデータだけが残ります。

例えば元データが

customer_id status
1 1
1 1
2 1
2 1

だった場合、

グループは次のようになります。

customer_id = 1
1
1

customer_id = 2
1
1

この場合MAX()の結果は?

各グループには1しか存在しません。

そのため、

MAX(status)

を実行すると

1の中の最大値 → 1

になります。

結果は次の通りです。

customer_id status
1 1
2 1

「じゃあMAX()って意味ないの?」

今回のケースでは、

計算結果だけを見るとほぼ意味がないように見えます。

なぜなら、

WHERE status = 1

によって、最初から1しか存在しないからです。

しかし、

SELECT
    customer_id,
    status
FROM orders
GROUP BY customer_id;

ではエラーになります。

そのため、

MAX(status)

を付けることで、

この列はちゃんと集計していますよ

とSQLに伝えている、、ということがわかりました


まとめ

今回学んだことを整理します。

  • GROUP BYは同じ値を持つ行をまとめる機能
  • GROUP BYした列以外は、そのままSELECTできない
  • SQLは「どの値を返せばいいか分からない」とエラーになる
  • MAX()などの集計関数を使うことで、返す値を明確に指定できる
  • WHERE句で1に絞り込まれている場合、MAX(status)の結果も1になる

私は最初、

値が1しかないならMAX()は不要では?

と思っていました。

しかし実際は、

GROUP BYのルールを守るために書かれている

というケースもあることが分かりました。

同じ疑問を持った方の参考になれば幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?