[解決済み】COUNT(*) vs. COUNT(1) vs. COUNT(pk): どちらが良いですか?[重複]。
質問
この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
ただし
COUNT(*)
LEFT結合では、下位テーブルが親テーブルにマッチしない場合でも1を返します。
SELECT boss.boss_id, COUNT(*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
というアドバイスに惑わされないでください。
*
は、テーブルから行全体を取得します。
*
が遅い。 その
*
で
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
しかし、それができないのです(
COUNT(tableNameHere)
標準SQLでは、フィールドにテーブル名と同じ名前を付けることが許されているからです。
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を使ったカウント
また、フィールドの名前がテーブル名と一致する場合、そのフィールドをNULL可能にするのは良い方法とは言えません。例えば、'Banana'、'Apple'、NULL、'Pears' という値が
fruit
フィールドを使用します。この場合、すべての行をカウントすることはできず、4行ではなく、3行しかカウントされません。
SELECT count(fruit) FROM fruit
RDBMS の中にはそのような原理(テーブルの行数を数えるために、COUNT のパラメータとしてテーブル名を受け付ける)を持つものもありますが、これは Postgresql で動作します(もし
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)
である。
一発芸
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
関連
-
[解決済み】SQL Server: 無効なカラム名
-
[解決済み] FROM のサブクエリにはエイリアスが必要です。
-
[解決済み] オペランド型の衝突:uniqueidentifierはintと互換性がない
-
[解決済み] リスト項目の出現回数を数えるにはどうしたらいいですか?
-
[解決済み] JavaScriptでオブジェクトのキー/プロパティの数を効率的にカウントする方法
-
[解決済み] jQuery: テーブルの行数を数える
-
[解決済み] 別のテーブルに一致する項目がない行を選択するにはどうすればよいですか?
-
[解決済み】文字列中のある文字の出現回数をカウントする
-
[解決済み】Count(*)とCount(1)の比較 - SQL Server
-
[解決済み] count > 1のレコードを検索するSQLクエリ
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】オペランド型の衝突:intはdateと互換性がない + INSERT文はFOREIGN KEY制約と衝突した
-
[解決済み】Teradata - 計算中に数値のオーバーフローが発生しました。
-
[解決済み] ORA-01790: 式は、対応する式と同じデータ型でなければならないエラーが発生するケース
-
[解決済み] WHERE x IN (5) vs WHERE x = 5 ...なぜINを使うのか?
-
[解決済み] エラー (ORA-00923: 期待された場所に FROM キーワードが見つかりませんでした)
-
[解決済み] ora-06553 pls-306 'ogc_x' の呼び出しで引数の数または種類が誤っている。
-
[解決済み] SQLで複数のGROUP BYを使用する場合とは?
-
[解決済み】Count(*)とCount(1)の比較 - SQL Server
-
[解決済み】MySQLでカラムに同じ値を持つ行を検索する
-
[解決済み】SQL Serverで重複する行を検索する。