私はしばしばこれらの3つのバリアントを見つけます:
SELECT COUNT(*) FROM Foo;
SELECT COUNT(1) FROM Foo;
SELECT COUNT(PrimaryKey) FROM Foo;
私が見る限り、それらはすべて同じことを行い、私は自分のコードベースで3つを使用していることに気付きます。ただし、同じことを異なる方法で行うのは好きではありません。どちらに固執すべきですか?それらのいずれかが他の2つよりも優れていますか?
COUNT(field)
またはCOUNT(*)
のいずれかを使用し、一貫して使用します。データベースでCOUNT(tableHere)
またはCOUNT(tableHere.*)
が許可されている場合は、それを使用します。
要するに、COUNT(1)
を何にも使用しないでください。それはワントリックポニーで、あなたが望むものをめったに行いません、そしてそれらのまれなケースではcount(*)
と同等です
count(*)
を使用結合を含め、すべてをカウントする必要があるすべてのクエリに*
を使用し、*
を使用します
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
ただし、LEFT結合にはCOUNT(*)
を使用しないでください。下位テーブルが親テーブルの何とも一致しない場合でも1を返すためです。
SELECT boss.boss_id, COUNT(*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
COUNTで*
を使用する場合、*
が遅いと言ってテーブルから行全体をフェッチすることを勧める人にだまされないでください。 SELECT COUNT(*)
と*
上のSELECT *
は互いに関係がなく、まったく異なるものであり、共通のトークン、つまり*
を共有するだけです。
実際、テーブル名と同じようにフィールドに名前を付けることが許可されていない場合、RDBMS言語デザイナーはCOUNT(tableNameHere)
にCOUNT(*)
と同じセマンティクスを与えることができます。例:
行をカウントするために、次のことができます。
SELECT COUNT(emp) FROM emp
そして、彼らはそれをより簡単にすることができます:
SELECT COUNT() FROM emp
LEFT JOINの場合、次のようになります。
SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
ただし、SQL標準ではテーブル名と同じ名前のフィールドに名前を付けることが許可されているため、それらはできません(COUNT(tableNameHere)
)。
CREATE TABLE fruit -- ORM-friendly name
(
fruit_id int NOT NULL,
fruit varchar(50), /* same name as table name,
and let's say, someone forgot to put NOT NULL */
shape varchar(50) NOT NULL,
color varchar(50) NOT NULL
)
また、フィールド名がテーブル名と一致する場合、フィールドをNULL可能にすることは推奨されません。 fruit
フィールドに 'Banana'、 'Apple'、NULL、 'Pears'の値があるとします。これはすべての行をカウントするわけではなく、4ではなく3だけを生成します
SELECT count(fruit) FROM fruit
一部のRDBMSはそのような原則を実行しますが(テーブルの行をカウントするために、COUNTのパラメーターとしてテーブル名を受け入れます)、これはPostgresqlで機能します(以下の2つのテーブルのいずれにもsubordinate
フィールドがない場合、フィールド名とテーブル名の間に名前の競合がない限り):
SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
しかし、テーブルにsubordinate
フィールドを追加すると、テーブルの行ではなくフィールド(null可能)をカウントするため、後で混乱を引き起こす可能性があります。
安全のために、以下を使用します。
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
count(1)
:ワントリックポニー特にCOUNT(1)
には、one-trickポニーであり、1つのテーブルクエリでのみ機能します。
SELECT COUNT(1) FROM tbl
ただし、結合を使用する場合、セマンティクスが混乱しない限り、このトリックはマルチテーブルクエリでは機能せず、特に次のように書くことはできません。
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.1)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
COUNT(1)の意味は何ですか?
SELECT boss.boss_id, COUNT(1)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
これですか...?
-- counting all the subordinates only
SELECT boss.boss_id, COUNT(subordinate.boss_id)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
それとも...?
-- or is that COUNT(1) will also count 1 for boss regardless if boss has a subordinate
SELECT boss.boss_id, COUNT(*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
慎重に考えれば、結合のタイプに関係なく、COUNT(1)
はCOUNT(*)
と同じであると推測できます。ただし、LEFT JOINの結果については、COUNT(1)
を次のように機能させることはできません:COUNT(subordinate.boss_id)
、COUNT(subordinate.*)
したがって、次のいずれかを使用します。
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.boss_id)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Postgresqlで動作します。セットのカーディナリティをカウントしたいのは明らかです。
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
セットのカーディナリティをカウントする別の方法は、非常に英語に似ています(テーブル名と同じ名前の列を作成しないでください): http://www.sqlfiddle.com/#!1/ 98515/7
select boss.boss_name, count(subordinate)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name
これはできません: http://www.sqlfiddle.com/#!1/98515/8
select boss.boss_name, count(subordinate.1)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name
これを行うことはできますが、これにより誤った結果が生成されます。 http://www.sqlfiddle.com/#!1/98515/9
select boss.boss_name, count(1)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name
それらの2つは常に同じ答えを生成します。
COUNT(*)
は行数をカウントしますCOUNT(1)
は行数もカウントしますpk
が主キーであり、値にnullが許可されていないと仮定すると、
COUNT(pk)
は行数もカウントしますただし、pk
がnull以外に制約されていない場合は、別の答えが生成されます。
COUNT(possibly_null)
は、列possibly_null
にNULL以外の値がある行の数をカウントします。
COUNT(DISTINCT pk)
は、行の数もカウントします(主キーは重複を許可しないため)。
COUNT(DISTINCT possibly_null_or_dup)
は、列possibly_null_or_dup
の個別の非NULL値の数をカウントします。
COUNT(DISTINCT possibly_duplicated)
は、possibly_duplicated
句が列にある場合に、列NOT NULL
の個別の(必然的にnullでない)値の数をカウントします。
通常、私はCOUNT(*)
;と書きます。これは、SQLの元の推奨表記法です。同様に、EXISTS
節では、元の推奨表記であるため、通常WHERE EXISTS(SELECT * FROM ...)
と記述します。代替案にメリットはありません。オプティマイザは、より不明瞭な表記を確認する必要があります。
これは、使用しているデータベースのタイプと、場合によってはテーブルのタイプによって異なります。
たとえば、MySQLを使用すると、count(*)
はMyISAMテーブルでは高速になりますが、InnoDBでは低速になります。 InnoDBでは、count(1)
またはcount(pk)
を使用する必要があります。
オンラインの書籍 は「COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )
」と言います
「1」は非ヌル式なので、COUNT(*)
と同じです。オプティマイザーはそれをtrivialとして認識するため、同じプランを提供します。 PKは一意であり、(少なくともSQL Serverでは)NULLではないため、COUNT(PK)
= COUNT(*)
これはEXISTS (SELECT * ...
またはEXISTS (SELECT 1 ...
と似た神話です
ANSI 92仕様 、セクション6.5、一般規則、ケース1を参照してください
a) If COUNT(*) is specified, then the result is the cardinality
of T.
b) Otherwise, let TX be the single-column table that is the
result of applying the <value expression> to each row of T
and eliminating null values. If one or more null values are
eliminated, then a completion condition is raised: warning-
null value eliminated in set function.
少なくともOracleでは、すべて同じです。 http://www.oracledba.co.uk/tips/count_speed.htm