我经常会发现以下三种变体:
SELECT COUNT(*) FROM Foo; SELECT COUNT(1) FROM Foo; SELECT COUNT(PrimaryKey) FROM Foo;
据我所知,它们都做相同的事情,我发现自己在代码库中使用了这三个。但是,我不喜欢用不同的方式做同样的事情。我应该坚持哪一个?他们中的任何一个都比其他两个更好吗?
使用COUNT(field)或COUNT(*),并坚持使用,如果数据库允许COUNT(tableHere)或COUNT(tableHere.*),则使用它。
COUNT(field)
COUNT(*)
COUNT(tableHere)
COUNT(tableHere.*)
简而言之,不要使用COUNT(1)任何东西。这是一招的小马,很少会做你想做的事,在那些罕见的情况下,相当于count(*)
COUNT(1)
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
那些建议不要*在COUNT中使用时,它会从您的表中提取整行,这*很慢,因此请不要上当。该*上SELECT COUNT(*)和SELECT *无轴承对方,他们是完全不同的事情,他们只是共用一个道理,即*。
SELECT COUNT(*)
SELECT *
实际上,如果不允许使用与表名称相同的名称来命名字段,则RDBMS语言设计器可以提供COUNT(tableNameHere)与相同的语义COUNT(*)。例子:
COUNT(tableNameHere)
为了计数行,我们可以这样:
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 )
而且,如果字段的名称与表名称匹配,则使字段可为空也不是一个好习惯。假设您在fruit字段上具有值“香蕉”,“苹果”,NULL,“梨” 。这不会计算所有行,只会产生3,而不是4
fruit
SELECT count(fruit) FROM fruit
尽管某些RDBMS遵循这种原则(用于计数表的行,它接受表名作为COUNT的参数),但是这将在Postgresql中有效(如果subordinate下面两个表中的任何一个都没有字段,即只要没有字段名称和表名称之间的名称冲突):
subordinate
但这会在以后引起混淆,如果我们将subordinate在表中添加一个字段,因为它将计算该字段(可能为空),而不是表中的行。
因此,为了安全起见,请使用:
count(1)
特别是COUNT(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(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
//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