CodeGym /コース /SQL SELF /NULLが集約関数に与える影響: SUM(), COUNT(), AVG(), MIN(), MAX()

NULLが集約関数に与える影響: SUM(), COUNT(), AVG(), MIN(), MAX()

SQL SELF
レベル 9 , レッスン 2
使用可能

集約関数っていうのは、複数行のデータをまとめて処理して、1つの結果を返す関数のことだよ。PostgreSQLだと、よく使う集約関数はこんな感じ:

  • SUM() — データの合計。
  • AVG() — 平均値を出す。
  • MIN() — 最小値を探す。
  • MAX() — 最大値を探す。
  • COUNT() — 行数を数える。

一見シンプルで、カラムや式を関数に渡せば結果が返ってくる。でも、もしカラムにNULLがあったらどうなる?

集約でのNULLの挙動:ざっくりまとめ

ここからが面白いところ:

  • SUM()AVG()NULLを無視する。1つでもNULLがあれば、その行は計算に入らない。まあ、パーティーに来なかった人の分は合計に入らないって感じ。平均も、値が足りないなら計算できないしね。
  • MIN()MAX()NULLをスルー。NULLじゃないデータだけで最小・最大を探す。だから、誕生日を入力し忘れた一番若い社員を探しても、NULLは選ばれないよ。
  • COUNT(*)全行をカウントする。NULLがあっても関係なし。でもCOUNT(column)は、そのカラムに値がある行だけ数える。つまりNULLは無視される。

じゃあ、実際に例で見てみよう。

NULL入り集約関数の使い方例

例えば、students_scoresテーブルには学生のテストスコアが入ってる:

student_id name score
1 アリサ 85
2 ボブ NULL
3 チャーリー 92
4 ダナ NULL
5 エレナ 74

じゃあ、いくつかクエリを投げて結果を見てみよう:

  1. 全スコアの合計:SUM()
SELECT SUM(score) AS total_score
FROM students_scores;

結果:

total_score
251

見ての通り、NULLは合計に入ってない。アリサ(85)、チャーリー(92)、エレナ(74)で合計251。ボブとダナはスルーされた。

  1. 平均スコア:AVG()
SELECT AVG(score) AS average_score
FROM students_scores;

結果:

average_score
83.67

ここでもNULLは無視されて、スコアがある人だけで平均を計算:(85 + 92 + 74) / 3 = 83.67

  1. 最小・最大スコア:MIN()MAX()
SELECT
    MIN(score) AS min_score, 
    MAX(score) AS max_score 
FROM students_scores;

結果:

min_score max_score
74 92

これもシンプル。NULLは無視されて、最小は74、最大は92。

  1. 行数カウント:COUNT(*) vs COUNT(column)
SELECT
    COUNT(*) AS total_rows, 
    COUNT(score) AS non_null_scores 
FROM students_scores;

結果:

total_rows non_null_scores
5 3
  • COUNT(*)scoreNULLでも全行をカウント。
  • COUNT(score)scoreに値がある行だけカウント。

実践ケース

いくつか実践的な例も見てみよう。

例1:給与がある・ない社員のカウント

例えば、employeesテーブルに給与が入ってるとする。

id name salary
1 Alex Lin 50000
2 Maria Chi NULL
3 Anna Song 60000
4 Otto Art NULL
5 Liam Park 55000

給与を入力した社員と、してない社員の数を知りたい。

SELECT
    COUNT(*) AS total_employees,
    COUNT(salary) AS employees_with_salary,
    COUNT(*) - COUNT(salary) AS employees_without_salary
FROM employees;

ここで:

  • COUNT(*)は社員の総数。
  • COUNT(salary)は給与を入力した社員の数。
  • 給与なし社員は、総数から給与あり社員を引くだけ。

結果

total_employees employees_with_salary employees_without_salary
5 3 2

例2:商品価格の平均(未入力データあり)

君は魔法ショップのオーナーで、productsテーブルのpriceカラムには一部商品で価格が未入力。

id name price
1 Magic Wand 150
2 Enchanted Cloak NULL
3 Potion Bottle 75
4 Spell Book 200
5 Crystal Ball NULL

価格が入力されてる商品のみで平均を知りたい。

SELECT AVG(price) AS average_price
FROM products;

結果:

average_price
141.6667

もし価格未入力の商品にデフォルト値(例えば0)を入れたいなら、次のレクチャーで出てくるCOALESCE()関数を使えばOK!

例3:学生の最小・最大年齢を探す

studentsテーブルには学生の年齢が入ってるけど、一部は年齢不明(NULL)。

id name age
1 Alex Lin 20
2 Maria Chi NULL
3 Anna Song 19
4 Otto Art 22
5 Liam Park NULL

一番若い&一番年上の学生を知りたい。

SELECT
    MIN(age) AS youngest_student,
    MAX(age) AS eldest_student
FROM students;

結果:

youngest_student eldest_student
19 22

このクエリは年齢が入力されてる学生だけで最小・最大を返す。NULLはまたスルー。

注意点・落とし穴

NULL入り集約を使うときは、次のポイントに気をつけて:

  • SUM()AVG()ではNULLは無視される。空の値を計算に入れたくないときに便利。
  • カラムにNULLがある行もカウントしたいならCOUNT(*)を使おう。
  • MIN()MAX()NULLは結果に影響しない。ただし、カラムが全部NULLなら結果もNULLになる。

NULLと付き合うコツ

  1. 目的に合わせて考えよう。 クエリでNULLを無視していいかどうかをちゃんと考えよう。AVG()みたいに無視したいときもあれば、全体数を数えたいときはNULLも含めたい。
  2. COALESCE()を活用しよう。 計算でNULLをデフォルト値に置き換えたいときはCOALESCE()が便利(これは次のレクチャーで!)。
  3. COUNT(*)COUNT(column)の違いに注意。 これ、初心者がよくやるミス。前者は全行、後者は値がある行だけカウント。

これで、ひっそりと存在感を放つNULLが集約にどう影響するかバッチリ!これを知ってれば、思わぬ落とし穴も回避できるし、NULLをうまく使いこなせるよ。次のレクチャーでは、COALESCE()という強力な武器でNULLをもっと自在に操る方法を学ぼう!

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION