$ man count
COUNT
集約関数行数を数える。数え方が 3 通りあり、NULL の扱いが違う。
呼び出しの形
COUNT(*) COUNT(式) COUNT(DISTINCT 式)
つまずきやすいところ
COUNT(列)は NULL を数えません。「行数のつもりで列を渡していた」は件数がずれるいちばん多い原因です。行数ならCOUNT(*)を使ってください。1 行も無いときの
COUNT(*)は 0 を返しますが、GROUP BYを付けた場合は行そのものが返りません。「0 件の部署が一覧に出てこない」のはこれが理由で、出したいなら部署表から外部結合します。COUNT(DISTINCT 列)は重複を除くために内部で並べ替えるので、行数が多いとCOUNT(*)よりはっきり遅くなります。
実行例
結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。
SELECT COUNT(*) AS zen, COUNT(busho_id) AS busho_ari, COUNT(DISTINCT busho_id) AS busho_no_kazu FROM shain
| zen | busho_ari | busho_no_kazu |
|---|---|---|
| 18 | 16 | 6 |
1 行
社員は 18 行。うち 2 人は所属なし(busho_id が NULL)なので COUNT(busho_id) は 16 になります。社員が所属している部署の種類は 6 です(部署表には 7 行ありますが、社員が 0 人の部署は数えられません)。
SELECT busho_id, COUNT(*) AS ninzu FROM shain GROUP BY busho_id ORDER BY busho_id
| busho_id | ninzu |
|---|---|
| 1 | 1 |
| 2 | 4 |
| 3 | 4 |
| 4 | 3 |
| 5 | 2 |
| 7 | 2 |
| NULL | 2 |
7 行
所属なしの行は busho_id が NULL のグループとしてまとまります。
説明
COUNT は 3 つの形で意味が変わります。ここを取り違えると、「件数が合わない」の原因になります。
COUNT(*)… 行そのものを数えます。列の中身は見ないので NULL があっても減りませんCOUNT(列)… その列が NULL でない行だけを数えますCOUNT(DISTINCT 列)… NULL を除いたうえで、値の種類を数えます
「全体で何行あるか」を知りたいなら COUNT(*)、「その項目が埋まっている行が何行あるか」を知りたいなら COUNT(列) です。
GROUP BY と組み合わせると、グループごとの件数になります。グループが 1 つも作られない場合(元の行が 0 行)は結果そのものが 0 行になり、0 という値は返りません。
ほかの製品でも通るか
主要 7 製品で通用 そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database / IBM Db2
次に読む
根拠にした一次情報
- PostgreSQL 18 マニュアル: 集約関数(2026-09-02 確認)