SQLのCOUNT関数は何が違う?COUNT(*)・COUNT(列名)・NULLの数え方をやさしく解説
まず結論:COUNTは「何を数えたいか」で選ぶ
SQLのCOUNT関数は、同じように件数を数える関数に見えても、書き方によって数えている対象が変わります。
COUNT(*)は条件に一致した行数を数える書き方です。
COUNT(列名)は指定した列にNULLではない値が入っている行だけを数える書き方です。
そのため、テーブルには4行あるのにCOUNT(列名)の結果が2になるような差が起きます。
この差を理解するには、COUNTが「行を数えているのか」「列の値を数えているのか」を分けて考えることが大切です。
特にSQL初心者がつまずきやすいのは、COUNTという名前だけを見て「どの書き方でも同じ件数になるはず」と考えてしまう点です。
実際には、全体の件数を見たいのか、入力済みの件数を見たいのかで、使うべきCOUNTは変わります。
最初にこの考え方を押さえておくと、集計結果が想定と違ったときにも原因を探しやすくなります。
COUNT(*)は条件に一致した行数を数える
COUNT(*)は、SELECTの対象になった行そのものを数えます。
列の中身がNULLかどうかは基本的に関係ありません。
WHERE句で条件を指定している場合は、その条件に一致した行数を数えます。
つまり、テーブル全体のレコード数や、条件に合うデータ件数を知りたいときに向いています。
たとえば、社員テーブルに何人分のレコードがあるかを確認したい場合は、部署名や電話番号がNULLかどうかを気にする必要はありません。
そのような場面では、行が存在していること自体を数えたいので、COUNT(*)が自然です。
COUNT(列名)はNULLではない値だけを数える
COUNT(列名)は、指定した列に値が入っている行だけを数えます。
指定した列がNULLの行は、COUNTの対象から外れます。
たとえばdepartment列にNULLが入っている行がある場合、COUNT(department)ではその行は数えられません。
この仕様を知らないと、全行数を確認したつもりなのに、結果が少なく見えることがあります。
ただし、COUNT(列名)が悪い書き方というわけではありません。
未入力を除いた件数を知りたいときには、むしろCOUNT(列名)が目的に合った書き方になります。
全体件数と入力済み件数で使い分ける
全体の行数を知りたいならCOUNT(*)を使います。
特定の列に値が入っている件数を知りたいならCOUNT(列名)を使います。
COUNTの使い分けで迷ったときは、行を数えたいのか、値が入っている行だけを数えたいのかを先に決めると判断しやすくなります。
たとえば「登録ユーザー数」を知りたいならCOUNT(*)が向いています。
一方で「メールアドレス登録済みのユーザー数」を知りたいならCOUNT(email)が向いています。
このように、知りたい件数の意味を言葉にしてからSQLを書くと、COUNTの選び間違いを減らせます。
COUNT関数の違いを比較表で整理する
COUNT関数には、COUNT(*)、COUNT(列名)、COUNT(1)、COUNT(DISTINCT 列名)などの書き方があります。
どれも件数を数えるために使いますが、数える対象やNULLの扱いが少しずつ違います。
先に全体像を表で整理しておくと、どの書き方を選べばよいか判断しやすくなります。
特にCOUNT(*)とCOUNT(列名)は見た目が似ているため、同じような結果になると思い込みやすいです。
しかし、NULLを含むデータでは結果に差が出るため、比較して覚えるのがおすすめです。
| 書き方 | 数える対象 | NULLの扱い | 主な用途 |
|---|---|---|---|
| COUNT(*) | 条件に一致した行 | 列のNULLに影響されない | 全行数や条件一致件数の確認 |
| COUNT(列名) | 指定列のNULL以外の値 | NULLは数えない | 入力済み件数の確認 |
| COUNT(1) | 定数を持つ行 | 列のNULLに影響されない | COUNT(*)と同じような行数確認 |
| COUNT(DISTINCT 列名) | 重複を除いた列の値 | NULLは通常数えない | 種類数やユニーク数の確認 |
数える対象の違い
COUNT(*)は行を数えます。
COUNT(列名)は指定した列の値を数えます。
COUNT(1)は各行に対して定数1を見ているような書き方です。
COUNT(DISTINCT 列名)は、指定した列の値から重複を除いた種類数を数えます。
同じCOUNTでも、行数、値の数、定数、種類数というように、見ているものが違います。
この違いを曖昧にしたまま使うと、集計結果の意味を誤って解釈してしまいます。
NULLの扱いの違い
COUNT結果がズレる大きな原因はNULLです。
COUNT(*)やCOUNT(1)は、列の値がNULLでも行として数えます。
COUNT(列名)は、指定列がNULLの行を数えません。
COUNT(DISTINCT 列名)も、重複を除いた値を数えるときにNULLを通常の値として数えない扱いになります。
NULLは「値がない」状態なので、値を数えるCOUNTでは対象外になりやすいと考えると理解しやすいです。
一方で、行そのものを数えるCOUNT(*)では、NULLを持つ列があっても行は存在しているため件数に含まれます。
実務での主な使いどころ
テーブルの件数を確認したいときはCOUNT(*)が分かりやすいです。
入力済みの項目数を確認したいときはCOUNT(列名)が向いています。
部署数やカテゴリ数のように種類数を見たいときはCOUNT(DISTINCT 列名)を使います。
実務では、単に「件数」と言っても、全件数、入力済み件数、ユニーク件数など意味が分かれます。
そのため、SQLを書く前に「この件数は何を表しているのか」を確認することが重要です。
サンプルデータでCOUNT(*)とCOUNT(列名)の結果差を確認する
COUNT(*)とCOUNT(列名)の違いは、NULLを含むサンプルデータで見ると理解しやすくなります。
ここでは、社員テーブルにdepartment列があり、一部の行でdepartmentがNULLになっている例を考えます。
同じテーブルを数えているのに結果が変わる理由は、COUNTが見ている対象が違うためです。
文章だけで理解しようとすると少し抽象的ですが、表と結果を並べると差がはっきり見えます。
NULLを含むサンプルテーブルを用意する
次のようなemployeesテーブルがあるとします。
| id | name | department |
|---|---|---|
| 1 | 佐藤 | 営業 |
| 2 | 鈴木 | NULL |
| 3 | 高橋 | 開発 |
| 4 | 田中 | NULL |
このテーブルには4行あります。
しかし、department列に値が入っているのは営業と開発の2行だけです。
鈴木と田中のdepartmentはNULLなので、部署がまだ未設定の状態だと考えられます。
このように、行は存在していても、特定の列だけ値が入っていないケースは実務でもよくあります。
COUNT(*)とCOUNT(department)を比較する
同じテーブルに対して、次のようにCOUNT(*)とCOUNT(department)を実行します。
| SQL | 結果 |
|---|---|
| SELECT COUNT(*) FROM employees; | 4 |
| SELECT COUNT(department) FROM employees; | 2 |
COUNT(*)の結果は4です。
COUNT(department)の結果は2です。
このように、同じテーブルでも書き方によって結果が変わります。
COUNT(*)は4人分の社員レコードを数えています。
COUNT(department)は部署が入力されている社員だけを数えています。
件数が違う理由を分解して考える
COUNT(*)はemployeesテーブルの4行をそのまま数えます。
department列がNULLの行も、行として存在しているため件数に含まれます。
一方でCOUNT(department)は、departmentに値が入っている行だけを数えます。
NULLになっている鈴木と田中の行は、COUNT(department)の対象から外れます。
そのため、COUNT(*)は4、COUNT(department)は2という結果になります。
ここで重要なのは、COUNT(department)が社員数を数えているのではなく、departmentに値がある行数を数えているという点です。
「社員は4人いるが、部署が入力済みなのは2人」と読み替えると、結果の意味が分かりやすくなります。
COUNT(*)を使うべき場面
COUNT(*)は、行数を確認したい場面で使いやすい書き方です。
列の中身ではなく、データが何行あるかを知りたいときに向いています。
SQLを読む人にも「行数を数えている」と伝わりやすいため、基本の書き方として覚えておくと便利です。
全件数や条件一致件数を確認するだけなら、COUNT(*)を使うことで余計な誤解を避けやすくなります。
テーブル全体の件数を確認したいとき
テーブルに何件のデータが入っているかを確認したいときはCOUNT(*)を使います。
たとえば、ユーザー数、注文数、社員数など、レコードそのものの件数を知りたい場合です。
この用途では、特定の列がNULLかどうかは関係ありません。
ユーザー名がNULLかどうか、電話番号がNULLかどうかではなく、ユーザーの行が何件あるかを知りたいからです。
そのため、全体件数を確認するSQLではCOUNT(*)がもっとも意図に合いやすいです。
WHERE条件に一致した行数を数えたいとき
条件に一致する行数を数えたい場合もCOUNT(*)が分かりやすいです。
たとえば、statusがactiveのユーザー数や、作成日が今月の注文数を数える場合です。
WHERE句で対象行を絞り込み、その結果に含まれる行数をCOUNT(*)で数える考え方です。
この場合、COUNT(*)はテーブル全体ではなく、WHERE条件に残った行だけを数えます。
条件で絞った後の行数を見たいなら、COUNT(*)の意味はとても明確です。
行の存在を確認したいとき
特定の条件に合う行が存在するかを件数で確認したいときにもCOUNT(*)を使えます。
この場合も、どの列に値が入っているかではなく、行があるかどうかが重要です。
列のNULLに左右されたくないなら、COUNT(列名)ではなくCOUNT(*)を選ぶ方が安全です。
たとえば、あるユーザーが注文した履歴があるかどうかを確認する場合、注文レコードが存在するかが重要になります。
このような確認では、特定列のNULLによって件数が変わると判断を誤る可能性があります。
COUNT(列名)を使うべき場面
COUNT(列名)は、指定した列に値が入っている件数を知りたいときに使います。
全行数ではなく、未入力を除いた件数を確認したい場面に向いています。
NULLを除外する仕様を意図して使うなら、COUNT(列名)はとても便利です。
逆に、NULLを除外する意図がない場合は、COUNT(列名)を使う前に目的を確認した方が安全です。
未入力を除いた件数を数えたいとき
メールアドレスが登録されているユーザー数を数えたい場合は、COUNT(email)のように書けます。
部署が設定されている社員数を数えたい場合は、COUNT(department)で確認できます。
このように、値が入っている行だけを数えたいときはCOUNT(列名)が役立ちます。
未入力の行を除外したいときには、COUNT(列名)のNULLを数えない性質がそのままメリットになります。
「全員の数」ではなく「入力済みの人数」を知りたい場面だと考えると分かりやすいです。
入力率や設定済み件数を見たいとき
COUNT(列名)は、入力率や設定済み件数を確認するときにも使えます。
たとえば、プロフィール画像を設定済みのユーザー数や、電話番号を登録済みの顧客数を数える場合です。
NULLを未入力として扱う設計なら、COUNT(列名)によって入力済みの件数を簡単に確認できます。
さらに、COUNT(*)とCOUNT(列名)を組み合わせれば、全体のうち何件が入力済みかを比較できます。
この考え方は、データ品質の確認や入力状況のレポートにも使いやすいです。
全件数確認に使うとズレる理由
COUNT(列名)を全行数確認のつもりで使うと、結果が少なくなることがあります。
指定列にNULLが含まれていると、その行はCOUNTの対象から外れるためです。
全体件数を確認したい場合は、COUNT(列名)ではなくCOUNT(*)を使うのが基本です。
特に、後からNULLを許可するようにテーブル設計が変わった場合、COUNT(列名)の結果が以前と変わる可能性があります。
集計SQLを保守するときは、その列が本当にNULLにならないのかも確認しておくと安心です。
COUNT(1)とCOUNT(*)の違いをどう考えるか
COUNT(1)とCOUNT(*)は、どちらも行数を数える目的で見かける書き方です。
昔からCOUNT(1)の方が速いと言われることがありますが、現在の多くのDBMSでは単純にそう断定できません。
実務では、性能差を思い込みで判断するより、意図が伝わりやすい書き方を選ぶことが大切です。
COUNT(1)を見ると、1という列を数えているように感じるかもしれませんが、実際には定数を指定している書き方です。
そのため、COUNT(列名)とは意味が異なります。
COUNT(1)は定数を数える書き方
COUNT(1)は、各行に対して定数の1を指定して数える書き方です。
ここでの1は列番号という意味ではありません。
指定した列がNULLかどうかを見るCOUNT(列名)とは考え方が違います。
定数1はNULLではないため、対象行がある限りカウントされます。
そのため、COUNT(1)は特定列のNULLに左右されにくい書き方です。
全行数を数える用途ではCOUNT(*)と同じように使われる
COUNT(1)は、全行数を数える用途ではCOUNT(*)と同じような結果になります。
行ごとに定数1があるものとして数えるため、特定の列のNULLには左右されません。
そのため、COUNT(1)とCOUNT(*)のどちらを見ても、行数確認のSQLだと読み取れることが多いです。
ただし、SQLを読み慣れていない人にとっては、COUNT(1)よりCOUNT(*)の方が意図を理解しやすい場合があります。
チームでSQLを共有するなら、読み手に伝わるかどうかも大切な判断基準です。
迷ったらCOUNT(*)を基本にする
特別な理由がないなら、全行数を数えるときはCOUNT(*)を基本にすると分かりやすいです。
COUNT(*)はSQLを読む人に対して、行全体を数えている意図が伝わりやすい書き方です。
性能を理由にCOUNT(1)を選ぶ場合は、利用しているDBMSの実行計画や公式情報を確認してから判断する方が安全です。
古い知識や聞きかじりだけでCOUNT(1)を選ぶと、可読性を下げるだけになることもあります。
まずはCOUNT(*)を基本にし、プロジェクトのルールがある場合はそれに合わせるのが現実的です。
GROUP BYとCOUNTを組み合わせるときの注意点
GROUP BYとCOUNTを組み合わせると、グループごとの件数を集計できます。
ただし、COUNT(*)を使うかCOUNT(列名)を使うかで、NULLを含むグループの見え方が変わることがあります。
特に、NULLのグループが表示されているのにCOUNT(列名)の結果が0になるケースは誤解しやすいポイントです。
GROUP BYではグループを作る列と、COUNTで数える対象を分けて考える必要があります。
ここを混同すると、集計結果の意味を読み違えてしまいます。
COUNT(*)ならグループごとの行数を数えられる
departmentごとに社員数を数えるような場合、COUNT(*)は各グループに属する行数を数えます。
departmentがNULLの行も、NULLというグループとしてまとめられることがあります。
その場合、COUNT(*)ではNULLグループに属する行数も集計結果に含まれます。
つまり、部署が未設定の社員が2人いるなら、NULLグループのCOUNT(*)は2になります。
部署名が入力されているかどうかではなく、そのグループに何行あるかを数えるためです。
COUNT(列名)ではNULLグループが0になることがある
COUNT(department)のように、GROUP BYしている列そのものをCOUNTすると注意が必要です。
departmentがNULLのグループでは、department列の値がすべてNULLです。
そのため、グループ自体は存在しても、COUNT(department)の結果は0になることがあります。
この結果を見ると、NULLグループに行がないように誤解するかもしれません。
しかし実際には、グループに行は存在していて、COUNT(department)がNULLを数えていないだけです。
集計レポートで起きやすい読み違い
部署別人数やカテゴリ別件数のレポートでは、COUNTの選び方を間違えると結果を誤読しやすくなります。
人数を数えたいならCOUNT(*)、部署名が入力されている件数を数えたいならCOUNT(department)のように、目的を分ける必要があります。
集計結果が想定より少ない場合は、COUNT(列名)でNULLを除外していないかを確認しましょう。
レポートの見出しが「部署別人数」なのにCOUNT(department)を使っていると、未設定の行が正しく人数として見えない可能性があります。
集計項目の名前とSQLのCOUNT対象が一致しているかを確認することも大切です。
COUNT(DISTINCT 列名)は重複を除いた種類数を数える
COUNT(DISTINCT 列名)は、指定した列の値から重複を除いて数える書き方です。
COUNT(列名)が値の入っている行数を数えるのに対し、COUNT(DISTINCT 列名)は値の種類数を数えます。
同じCOUNTでも、目的がかなり違うため混同しないようにしましょう。
COUNT(DISTINCT)は、ユニーク数を知りたいときに便利です。
ただし、行数を知りたい場面で使うと、思ったより少ない件数になることがあります。
値の種類数を数えたいときに使う
部署の種類数、カテゴリの種類数、購入したユーザーのユニーク数などを知りたい場合にCOUNT(DISTINCT 列名)を使います。
たとえばdepartment列に営業、営業、開発が入っている場合、COUNT(department)は3ですがCOUNT(DISTINCT department)は2になります。
重複した値を1つとして扱いたいときに便利です。
アクセスログで訪問回数ではなく訪問ユーザー数を知りたい場合にも、COUNT(DISTINCT user_id)のような考え方を使います。
このように、延べ件数とユニーク件数を分けたいときに役立ちます。
NULLは通常カウント対象にならない
COUNT(DISTINCT 列名)でも、NULLの扱いには注意が必要です。
一般的に、COUNT(DISTINCT 列名)はNULLをカウント対象に含めません。
NULLを1種類として数えたい場合は、DBMSの仕様やCOALESCEなどを使った変換を確認する必要があります。
たとえばNULLを「未設定」という文字列に置き換えてから数えると、未設定も1種類として扱える場合があります。
ただし、NULLを置き換えると集計の意味が変わるため、レポート上の意図を明確にしてから使う必要があります。
COUNT(列名)とは数えているものが違う
COUNT(列名)は、指定列に値が入っている行数を数えます。
COUNT(DISTINCT 列名)は、指定列に入っている値の種類数を数えます。
行数を見たいのか、種類数を見たいのかで使う関数を選びましょう。
同じ列を対象にしていても、COUNT(列名)とCOUNT(DISTINCT 列名)では結果が大きく変わることがあります。
件数が想定より少ない場合は、DISTINCTで重複を除いていないかも確認しましょう。
NULLの件数だけを数える方法
COUNT(*)とCOUNT(列名)の違いを利用すると、NULLの件数だけを求めることもできます。
実務では、未入力データの件数を確認したい場面があります。
そのようなときは、全体件数と入力済み件数の差を見る方法や、CASE式で明示的に数える方法があります。
NULLの件数を把握できると、入力漏れやデータ品質の確認にも役立ちます。
COUNT(*) – COUNT(列名)で求める
NULLの件数は、COUNT(*)からCOUNT(列名)を引くことで求められます。
たとえばdepartment列のNULL件数を知りたいなら、COUNT(*) – COUNT(department)という考え方です。
全行数からdepartmentが入力済みの件数を引くため、残りがdepartmentがNULLの件数になります。
サンプルテーブルではCOUNT(*)が4、COUNT(department)が2なので、departmentがNULLの件数は2です。
この方法は短く書けるため、COUNTの仕様を理解している人には読みやすいです。
CASE式で明示的に数える
NULLの条件をはっきり書きたい場合は、CASE式を使う方法もあります。
たとえば、department IS NULLのときだけ1を足すような集計にすれば、NULLの件数を明示的に数えられます。
読み手に「NULLを数えている」と伝えたい場合は、CASE式の方が分かりやすいことがあります。
条件が複雑になる場合や、NULL以外の特定条件も一緒に数えたい場合にもCASE式は便利です。
SQLが少し長くなっても、意図がはっきりするなら保守しやすくなります。
読みやすさと保守性で選ぶ
COUNT(*) – COUNT(列名)は短く書けるのが利点です。
CASE式は少し長くなりますが、条件が見えやすいのが利点です。
チームで読むSQLなら、短さだけでなく、意図がすぐ伝わるかどうかも考えて選びましょう。
簡単なNULL件数なら差分で十分な場合があります。
一方で、将来条件が増えそうな集計や、SQLに不慣れな人も読むレポートではCASE式の方が親切な場合があります。
COUNT結果が合わないときの確認手順
COUNTの結果が想定と違うときは、いきなりSQL全体を疑うより、原因を順番に切り分けると確認しやすくなります。
特に、COUNT(列名)を使っている場合はNULLの影響を最初に確認するのがおすすめです。
そのうえで、WHERE条件、GROUP BY、DISTINCTの有無を見直すと、件数差の理由を見つけやすくなります。
COUNTの結果が合わないときは、COUNT関数だけでなく、SQL全体の流れも確認する必要があります。
集計前に対象行が減っているのか、集計時に数え方が変わっているのかを分けて考えましょう。
NULLが含まれていないか確認する
COUNT(列名)の結果が少ないときは、まず指定列にNULLが含まれていないか確認します。
COUNT(*)とCOUNT(列名)を並べて実行すると、NULLによる差があるかを見つけやすくなります。
差分がある場合は、指定列がNULLの行がCOUNT(列名)から除外されている可能性があります。
この確認は、件数ズレの原因を早く見つけるうえでとても有効です。
全行数と入力済み件数を並べて見るだけで、NULLが原因かどうかの見当をつけられます。
WHERE条件で行が絞られていないか確認する
COUNT以前に、WHERE句で対象行が絞り込まれていることもあります。
条件の指定が想定より厳しいと、COUNT(*)でも結果は少なくなります。
COUNTの書き方だけでなく、FROM句やWHERE句で対象データがどう絞られているかも確認しましょう。
たとえば日付範囲、ステータス、削除フラグなどの条件によって、想定より対象行が少なくなることがあります。
件数が合わないときは、まず条件を外したCOUNTと条件付きCOUNTを比較すると原因を見つけやすいです。
GROUP BYやDISTINCTで数え方が変わっていないか確認する
GROUP BYを使うと、全体件数ではなくグループごとの件数になります。
DISTINCTを使うと、重複を除いた値の種類数になります。
COUNT結果が合わないと感じたら、行数を数えているのか、グループ単位で数えているのか、種類数を数えているのかを見直しましょう。
同じデータでも、集計単位が変わると結果はまったく違って見えます。
SQLの結果を確認するときは、COUNTの対象だけでなく、GROUP BYやDISTINCTが入っていないかも必ず確認しましょう。
COUNT関数の使い分け判断基準
COUNT関数は、目的から逆算して選ぶと迷いにくくなります。
大切なのは、行を数えたいのか、NULL以外の値を数えたいのか、重複を除いた種類数を数えたいのかを分けることです。
次のように目的別に整理すると、SQLを書くときの判断がしやすくなります。
COUNT関数の選び方は、構文の好みではなく、集計したい意味で決めるのが基本です。
| 目的 | 使うCOUNT | 理由 |
|---|---|---|
| 全行数を知りたい | COUNT(*) | 行そのものを数えるため |
| 条件に一致した行数を知りたい | COUNT(*) | WHERE後の行数を数えるため |
| 入力済み件数を知りたい | COUNT(列名) | NULLを除外できるため |
| 値の種類数を知りたい | COUNT(DISTINCT 列名) | 重複を除いて数えるため |
| NULL件数を知りたい | COUNT(*) – COUNT(列名) | 全体と入力済みの差を見られるため |
全行数ならCOUNT(*)
レコード数を知りたいときはCOUNT(*)を使います。
列のNULLに影響されないため、全体件数の確認に向いています。
まず件数確認をしたいだけなら、COUNT(*)を選ぶのが基本です。
「このテーブルに何件あるか」を知りたい場面では、特定の列を指定する必要はありません。
余計な列名を入れないことで、SQLの意図も読みやすくなります。
入力済み件数ならCOUNT(列名)
特定の列に値が入っている件数を知りたいときはCOUNT(列名)を使います。
NULLを除いた件数になるため、未入力を除外した集計に向いています。
ただし、全行数のつもりで使わないように注意が必要です。
COUNT(列名)は、指定列の入力状況を見たいときに使うものだと考えると分かりやすいです。
列名を指定した瞬間に、NULLの行が除外される可能性があることを意識しましょう。
種類数ならCOUNT(DISTINCT 列名)
値の種類数を知りたいときはCOUNT(DISTINCT 列名)を使います。
同じ値が複数行にあっても、重複を除いて数えられます。
行数と種類数は別物なので、集計の目的を確認してから使いましょう。
たとえば注文数と購入者数は違います。
注文数ならCOUNT(*)、購入者のユニーク数ならCOUNT(DISTINCT user_id)のように使い分けます。
迷ったら「行を数えるのか値を数えるのか」で考える
COUNT選びで迷ったら、最初に行を数えたいのか値を数えたいのかを考えます。
行を数えるならCOUNT(*)です。
値を数えるならCOUNT(列名)やCOUNT(DISTINCT 列名)を検討します。
この判断軸を持っておくと、COUNT(1)やDISTINCTが出てきても混乱しにくくなります。
SQLの見た目ではなく、集計結果にどんな意味を持たせたいかを基準にしましょう。
よくある質問
COUNT関数は基本を理解するとシンプルですが、NULLやCOUNT(1)、DISTINCTが絡むと迷いやすくなります。
ここでは、COUNT(*)とCOUNT(列名)の違いを調べる人が疑問に感じやすい点をまとめます。
短く確認したい場合は、このFAQから見直しても理解しやすいです。
本文を読んだあとに、実際のSQLで迷いやすいポイントを再確認する用途でも使えます。
COUNT(*)はNULLを含む列があっても数えますか?
COUNT(*)はNULLを含む列があっても行を数えます。
COUNT(*)は特定の列の値ではなく、条件に一致した行そのものを対象にするためです。
そのため、列の一部がNULLでも、行として存在していれば件数に含まれます。
NULLがある列を含むテーブルでも、全体のレコード数を知りたいならCOUNT(*)を使えば問題ありません。
列の値を数えているわけではない点を覚えておくと混乱しにくいです。
COUNT(列名)の結果が想定より少ないのはなぜですか?
COUNT(列名)は、指定した列がNULLの行を数えません。
結果が想定より少ない場合は、その列にNULLが含まれている可能性があります。
COUNT(*)とCOUNT(列名)を並べて確認すると、NULLによる差があるかを見つけやすいです。
また、WHERE条件で対象行が減っている場合もあります。
まずはCOUNT(*)、COUNT(列名)、NULL件数を並べて確認すると原因を切り分けやすくなります。
COUNT(*)とCOUNT(1)はどちらを使うべきですか?
迷った場合はCOUNT(*)を基本にすると分かりやすいです。
COUNT(*)は行数を数える意図が読み手に伝わりやすい書き方です。
COUNT(1)を使う場合は、チームのコーディングルールや利用しているDBMSの方針に合わせるとよいでしょう。
性能面を理由にどちらかを選ぶ場合は、推測ではなく実行計画や公式情報を確認するのが安全です。
可読性を重視するなら、COUNT(*)の方が無難な場面が多いです。
NULLの件数だけを数えるにはどうすればいいですか?
NULLの件数は、COUNT(*) – COUNT(列名)で求められます。
また、CASE式を使ってNULLの場合だけ数える方法もあります。
短く書きたいなら差分、意図を明確にしたいならCASE式が使いやすいです。
どちらの方法でも、COUNT(列名)がNULLを数えないという性質を理解していることが前提になります。
チームで共有するSQLでは、読み手がすぐ意味を理解できる書き方を選ぶとよいでしょう。
COUNT(DISTINCT 列名)でNULLは数えられますか?
COUNT(DISTINCT 列名)では、NULLは通常カウント対象に含まれません。
NULLも1つの種類として扱いたい場合は、COALESCEなどで別の値に変換してから数える方法を検討します。
ただし、DBMSによって細かな仕様や書き方が異なることがあるため、利用環境の仕様を確認しましょう。
NULLを変換して数える場合は、その変換後の値が本来のデータと衝突しないように注意が必要です。
たとえば「未設定」という文字列が実データとして存在する可能性がある場合は、集計結果の意味が曖昧になります。
まとめ:COUNTの違いはNULLの扱いまで見ると理解しやすい
SQLのCOUNT関数は、書き方によって数える対象が変わります。
COUNT(*)は行数を数え、COUNT(列名)は指定列のNULLではない値を数えます。
COUNT結果が想定と違うときは、まずNULLの扱いを確認すると原因を見つけやすくなります。
COUNT(1)やCOUNT(DISTINCT 列名)も含めて、COUNTは「何を数えているか」を意識することが重要です。
最後に、実務で迷わないためのポイントを整理します。
COUNT(*)は行数、COUNT(列名)はNULL以外
COUNT(*)は、条件に一致した行を数えます。
指定列の値がNULLかどうかには左右されません。
COUNT(列名)は、指定列に値が入っている行だけを数えるため、NULLを含む列ではCOUNT(*)より少ない結果になることがあります。
全体件数を知りたいならCOUNT(*)、入力済み件数を知りたいならCOUNT(列名)という基本を押さえておきましょう。
この違いだけでも、COUNTで起きる多くの疑問は解消しやすくなります。
COUNT(1)やCOUNT(DISTINCT)も目的で使い分ける
COUNT(1)は、行数確認の用途でCOUNT(*)と同じように使われることがあります。
ただし、読みやすさを重視するならCOUNT(*)を基本にするのが分かりやすいです。
COUNT(DISTINCT 列名)は、重複を除いた値の種類数を数えたいときに使います。
COUNT(列名)とCOUNT(DISTINCT 列名)は、どちらも列名を指定しますが、数えている意味は違います。
行数を見たいのか、ユニーク数を見たいのかを必ず確認しましょう。
集計ミスを防ぐにはNULLと集計単位を確認する
集計ミスを防ぐには、COUNTが行を数えているのか、値を数えているのかを確認することが大切です。
件数が合わないときは、NULL、WHERE条件、GROUP BY、DISTINCTの順に見直すと原因を切り分けやすくなります。
COUNT関数は「何を数えたいか」を先に決めれば、自然に正しい書き方を選びやすくなります。
SQLの集計は、関数名だけでなく、対象列、条件、集計単位までセットで読むことが大切です。
その習慣が身につくと、COUNTの結果を見ても慌てずに原因を確認できるようになります。