7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【SQL】COUNT関数を利用するときはNULLに気をつけよう!

Posted at

はじめに

SQLを利用するときには極力NULLを使わないようにしようと言われることが多いです。
SQLではNULLのデータが入っていることで奇妙な挙動をしてしまうことがあります。
その中の一つでCOUNT関数が存在します。

COUNT関数はその名の通りで条件に合致したデータ数を取得するための関数です。
例えば、条件に合致するデータが3件ある場合は3 と返却を行います。
簡単ですね。

ただ、データ内にNULLが含まれていると、COUNT関数の対象によって、返される値が異なる場合があります。

具体的には以下の通りです。

  • COUNT(*)
    • NULLのカラムを数える
  • COUNT(col_name)
    • NULLのカラムを数えない

なかなかとややこしいですね。。。

実際に例を見てみましょう。

以下のようなテーブルを考えます。

col_name
NULL
NULL
NULL
テーブル作成手順
CREATE TABLE COUNT_TEST (col_name INTEGER);

INSERT INTO COUNT_TEST VALUES (NULL);
INSERT INTO COUNT_TEST VALUES (NULL);
INSERT INTO COUNT_TEST VALUES (NULL);

COUNT(*), COUNT(col 実行比較

実際に両者の挙動を見てみましょう。

SELECT COUNT(*), COUNT(col_name) FROM COUNT_TEST;

+----------+-----------------+
| COUNT(*) | COUNT(col_name) |
+----------+-----------------+
|        3 |               0 |
+----------+-----------------+
1 row in set (0.00 sec)

実際に COUNT(*) では NULLのカラムを数えるのに対して、
COUNT(col_name) ではNULLのカラムを数えていないことがわかります。

活用例

COUNT関数の挙動は少しややこしいですが、この挙動を利用するとすこし便利な集計が可能になります。

会社の目標設定シートの提出日を記録している以下のようなテーブルを考えます。

CREATE TABLE employees
(employee_id   INTEGER PRIMARY KEY,
 department    VARCHAR(16) NOT NULL,
 submission_date     DATE);

INSERT INTO employees VALUES(100,  '営業部',   '2018-10-10');
INSERT INTO employees VALUES(101,  '営業部',   '2018-09-22');
INSERT INTO employees VALUES(102,  '開発部',   NULL);
INSERT INTO employees VALUES(103,  '開発部',   '2018-09-10');
INSERT INTO employees VALUES(200,  '開発部',   '2018-09-22');
INSERT INTO employees VALUES(201,  '経理部',   NULL);
INSERT INTO employees VALUES(202,  '総務部', '2018-09-25');

すべて目標設定シートを提出している部署を取得する

上記のテーブルからすべて目標設定シートを提出している部署を取得する 場合を考えましょう。

employeesmのデータですが、
提出のない社員のsubmission_dateのデータはNULLとなります。

ここで、COUNT関数の挙動が役に立ちます。

すべて目標設定シートを提出している = submission_dateカラムにデータが入っている

ということになるので、以下のようなSQLを実行することで、目的のデータを取得することができます。

SELECT 
  department
FROM
  employees 
GROUP BY
  department
HAVING 
  COUNT(*) = COUNT(submission_date);


+------------+
| department |
+------------+
| 営業部     |
| 総務部     |
+------------+
2 rows in set (0.01 sec)

まとめ

  • COUNT(*)
    • NULLのカラムを数える
  • COUNT(col_name)
    • NULLのカラムを数えない
7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?