【新人エンジニア向け】MySQLのSELECTとGROUP BYの関係は?主キーがあるとどうなる?

こんにちは。ゆうせいです。

新人エンジニアの方からよくある質問にこういったものがあります。

SELECTの後のカラムは、すべてGROUP BYに入れないといけないって聞いたんですけど、主キーがあると無視できるって本当ですか?」

一見すると少し混乱するポイントですよね。でも、ここをしっかり理解しておくと、SQLの読み書きがぐっと楽になります!


GROUP BYの基本ルール

まずはおさらいです。

SQLの標準(SQL標準仕様)では、GROUP BYを使うときに以下のルールがあります:

  • SELECT句で指定するカラムは、GROUP BY句でグループ化されているカラムか、集約関数(SUMやCOUNTなど)を使っているカラムでなければいけません。

集約関数の例

SELECT department, COUNT(*) FROM employees GROUP BY department;

この場合、departmentでグループ化して、その中の件数をCOUNT(*)で数えています。COUNT(*)は集約関数なので、OKです。


「主キーがあると例外になる」って本当?

ここが本題ですね。

結論から言うと:

MySQLでは、主キー(PRIMARY KEY)があるとき、そのカラムがGROUP BYに入っていなくてもSELECTで使える場合があります。

なぜかというと、MySQLはSQL標準に完全には従っていないからです。特に、ONLY_FULL_GROUP_BYというモードが関係してきます。


ONLY_FULL_GROUP_BYとは?

これはMySQLの設定モードの一つで、「GROUP BYを厳密にチェックするかどうか」を決めるものです。

設定されていない場合

SELECT id, name, COUNT(*) FROM users GROUP BY name;

このように、idがGROUP BYに入っていなくても、MySQLは文句を言わずに実行できてしまいます(結果は不定になる可能性あり)。

設定されている場合(SQL標準に近い)

SELECT id, name, COUNT(*) FROM users GROUP BY name;

この場合、idがGROUP BYに含まれていないのでエラーになります


主キーがあるときの特別なケース

さて、質問の「主キーなら逃れられる?」という点。

実は、テーブルの設計とクエリの組み方によっては、主キーがあることでMySQLが「グループごとに一意な値」と判断し、SELECTに出せる場合があります。

たとえば、次のようなケースです。

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(100)
);

このときに以下のクエリを書くと、

SELECT id, name FROM users GROUP BY id;

これはOKになります。なぜなら、idは主キーなので1行に一意ですし、nameも同じ行にあるので、一貫性が保証されるからです。

つまり、主キーでGROUP BYしている場合、その行にある他のカラムは一意に決まる、という判断が働きます。


例え話でイメージしてみよう

学校のクラスを想像してみてください。

  • クラスの名簿(テーブル)に、生徒番号(主キー)と名前が書いてあるとします。
  • 生徒番号でグループ分け(GROUP BY)をすれば、当然1人1グループになりますよね。

このとき、名前を表示しても「どの生徒か」が明確なので、矛盾がありません。

でも、もし「クラス名」でグループ分けしたとすると、1つのクラスに何人もいます。名前だけ表示すると、「どの生徒の名前?」とわからなくなりますよね。


簡単な図で整理

SELECT対象カラムGROUP BYに含まれている?エラーになる?(ONLY_FULL_GROUP_BYあり)
nameはいならない
ageいいえ集約関数を使っていないならなる
id(主キー)はいならない
id(主キー)いいえ一意性が保証されるならならないことも

まとめ:新人エンジニアへのアドバイス

  • MySQLは標準SQLよりゆるい仕様になっていることがある。
  • ONLY_FULL_GROUP_BYが有効なら、SELECTカラムはすべてGROUP BYに含めるか、集約関数を使おう。
  • 主キーがあると「一意性がある」と判断されてSELECTで使えることもあるが、それに頼るのは非推奨
  • 予期しない結果を避けるためにも、基本はすべて明示的にGROUP BYに含めるように心がけよう。

次に学ぶべきステップ!

  1. ONLY_FULL_GROUP_BYの確認方法SELECT @@sql_mode;でモードを確認してみましょう。
  2. 集約関数の使い方SUM, AVG, MAX, MIN, GROUP_CONCATなどを使った例を試してみましょう。
  3. ウィンドウ関数の導入:GROUP BYに頼らない集計方法もあります!

SQLの世界は奥が深いですが、ひとつずつ仕組みを理解すれば、確実に力になります!応援しています。質問があればいつでも聞いてくださいね。


セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。