GROUP BYなしの集計
単純な集計でテーブル全体が1行にまとめられる仕組みを学びます。
「GROUP BYなしの集計」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Interview Prepコースには全4レッスンが含まれています。
1つの集約関数で1行
面接官は、次の質問で基礎的な考え方を確認します。「GROUP BYなしで集約関数を使うと、どうなりますか?」
答えは、テーブル全体が1行に集約されるです。集約関数は、条件に一致するすべての行を、暗黙の1つのグループとして扱います。この「暗黙のグループ」というモデルを理解すると、その後に出てくる多くのルールも説明しやすくなるため、ここで丁寧に確認しましょう。
暗黙の単一グループ
GROUP BYなしで単独の集約関数を記述すると、SQLはすべての行を含む1つのグループが存在するかのように動作します。テーブルに何行あるかに関係なく、結果は必ずちょうど1行になります。テーブルが空の場合も同じです。
そのため、SELECT COUNT(*) FROM employees は1行を返し、その1つの数値でテーブル全体を要約します。
SELECT COUNT(*) AS total_employees
FROM employees;
-- always returns exactly one row複数の集約関数をまとめて使う
1つのSELECTに複数の集約関数を並べて記述できます。すべて同じ暗黙のグループを要約するため、複数の列を持つ1行だけが返されます。
これは「集計値をまとめて取得する」標準的なクエリです。4つの数値はすべて、同じ全行の集合を表しています。
SELECT
COUNT(*) AS num_rows,
SUM(salary) AS total_pay,
AVG(salary) AS avg_pay,
MAX(salary) AS top_pay
FROM employees;混在によるエラー
ここは最もよく問われるルールです。GROUP BYなしで、同じSELECT内に単独の集約関数と非集約列を混在させることはできません。
なぜでしょうか。集約関数は1行を生成しますが、通常の列には複数の値があります。そのうちどの値を表示すればよいのでしょうか。これは曖昧なため、標準SQLではエラーになります。
-- ERROR: name is not aggregated and there is no GROUP BY
SELECT name, MAX(salary)
FROM employees;曖昧になる理由
先ほどのテーブルで考えてみましょう。MAX(salary) はすべての行を1つの値に集約します。一方、name は行ごとに異なる値を持ちます。1つの要約行の1つのセルに、5人分の名前を入れることはできません。
データベースは推測で補うことを拒否します。これはGROUP BYのルールの根底にある原則と同じです。選択するすべての列は、集約されているか、グループの一部でなければなりません。 GROUP BYがない場合、使用できるのは集約関数だけです。
MySQLの緩い例外
ここで挙げておく価値のあるSQL方言上の注意点があります。以前の、または非 strict モードのMySQLでは、混在したクエリが許可され、必ずしも最高給与の従業員とは限らない任意の名前が返されることがありました。
ONLY_FULL_GROUP_BYを有効にした現代のMySQL(現在のデフォルト)では、他のデータベースと同様に拒否されます。これに触れるとSQL方言への理解を示せますが、混在したクエリは常に誤りとして扱ってください。
MAXの背後にある行を取得する
では、最高給与の従業員の名前を取得するにはどうすればよいでしょうか。混在したクエリを使ってはいけません。ORDER BY + LIMITを使うか、集約値と比較するサブクエリを使います。
最も簡単なのは ORDER BY/LIMIT を使う方法です。サブクエリを使う方法は応用が利き、最大値が同じすべての従業員を返せます。
-- Subquery: returns everyone earning the max
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);空のテーブルに対する集約関数
面接官が出してくるエッジケースです。「空のテーブルに対して単独の集約関数を使うと、何が返りますか?」
COUNT(*)は0を返します(1行、値は0)。SUM、AVG、MIN、MAXはNULLを返します(1行、値はNULL)。
重要なのは、必ず1行が返ることであり、0行になることはないという点です。この1行が保証されることが、GROUP BYなしの集約関数の要点です。
SELECT COUNT(*) AS c, SUM(salary) AS s, MAX(salary) AS m
FROM employees
WHERE 1 = 0;
-- one row: c=0, s=NULL, m=NULLWHEREでは集約関数を使えない
このモデルから導かれる別のルールとして、WHERE句に集約関数を置くことはできません。WHEREは集約が行われる前に個々の行を絞り込むためです。
集約結果で絞り込むには、GROUP BYとともにHAVINGを使うか、集約関数をサブクエリで包みます。実行順序の中でWHEREは早く実行されるため、集約結果を参照できません。
-- ERROR: aggregate not allowed in WHERE
-- SELECT * FROM employees WHERE salary > AVG(salary);
-- Correct: compare to the aggregate via subquery
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);GROUP BYなしの集約関数とGROUP BY
次のように対比してみましょう。
- GROUP BYなし:暗黙のグループが1つ = テーブル全体 = 結果は必ず1行。
- GROUP BY colあり:colの異なる値ごとに1つのグループ = グループごとに1行。
単独の集約関数は、グループ化する列が0個のGROUP BYにすぎません。同じ仕組みで、1つの大きな入れ物にまとめています。
-- Whole table: one row
SELECT AVG(salary) FROM employees;
-- Per department: one row each
SELECT department, AVG(salary)
FROM employees
GROUP BY department;説明する方法
簡潔な回答は次のとおりです。「GROUP BYなしの集約関数は、結果セット全体を1つの暗黙のグループとして扱い、空のテーブルに対しても必ず1つの要約行を返します。非集約列を一緒に選択することはできません。その値が曖昧になるためです。MAXやMINの背後にある行を取得するには、ORDER BY と LIMIT、または集約値と比較するサブクエリを使用します。」
理解度チェック
結果の形を予測してみましょう。
まとめ
GROUP BYなしの集約関数についてのまとめです。
- テーブル全体が1つの暗黙のグループになり、結果は必ず1行になります。
- 単独の集約関数と非集約列を混在させることはできません。
- 空のテーブルでは、
COUNT(*)= 0、その他の関数はNULLを返します。それでも1行です。 - 集約関数を
WHEREに置くことはできません。サブクエリまたはHAVINGを使用します。 - MIN/MAXの背後にある行を取得するには、ORDER BY + LIMIT またはサブクエリを使用します。
これで、集約関数に関する面接対策ドリルは完了です。
よくある質問
「GROUP BYなしの集計」レッスンは無料ですか?
はい。「GROUP BYなしの集計」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。
「GROUP BYなしの集計」で何を学びますか?
単純な集計でテーブル全体が1行にまとめられる仕組みを学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「GROUP BYなしの集計」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。