当前位置: 首页 > 面试题库 >

COUNT(*)vs.COUNT(1)vs.COUNT(pk):哪个更好?

尹昂雄
2023-03-14
问题内容

我经常会发现以下三种变体:

SELECT COUNT(*) FROM Foo;
SELECT COUNT(1) FROM Foo;
SELECT COUNT(PrimaryKey) FROM Foo;

据我所知,它们都做相同的事情,我发现自己在代码库中使用了这三个。但是,我不喜欢用不同的方式做同样的事情。我应该坚持哪一个?他们中的任何一个都比其他两个更好吗?


问题答案:

使用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

那些建议不要*在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

但是他们不能这样做(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计数

而且,如果字段的名称与表名称匹配,则使字段可为空也不是一个好习惯。假设您在fruit字段上具有值“香蕉”,“苹果”,NULL,“梨”
。这不会计算所有行,只会产生3,而不是4

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在表中添加一个字段,因为它将计算该字段(可能为空),而不是表中的行。

因此,为了html" target="_blank">安全起见,请使用:

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),这是 一招小马 ,它仅对一个表查询有效:

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): Count(*)vs Count(1) 您能告诉我什么是性能更好的(MySQL)吗?Count(*)还是count(1)? 问题答案: 这是MySQL的答案。 它们的性能完全相同-除非您使用MyISAM,否则存在特例。无论如何我总是用。 http://dev.mysql.com/doc/refman/5.1/en/group-by- functions.

  • 问题内容: 只是想知道您是否有人用光了,性能是否存在明显差异,或者这仅仅是过去的日子所养成的传统习惯? 具体的数据库是。 问题答案: 没有区别。 原因: 在线书籍上说“ ” “ 1”是非空表达式:因此与相同。优化器可以识别它是什么:琐碎的。 与或相同 例子: 相同的IO,相同的计划,作品 编辑,2011年8月 关于DBA.SE的类似问题。 编辑,2011年12月 在ANSI-92中专门提到(请查找

  • 问题内容: 我有一个这样的表: 我现在想获取所有具有多个值的条目。预期结果将是: 我试图做到这一点是这样的: 但是甲骨文不喜欢它。 所以我尝试了这个 …没有成功。 有任何想法吗? 问题答案: 使用该子句比较聚合。 另外,您需要根据要汇总的内容进行分组,以使查询正常运行。以下是一个开始,但是由于您缺少group by子句,因此仍然无法正常工作。您到底想算什么?

  • 本文向大家介绍count(*),count(1)和count(列名)的区别?相关面试题,主要包含被问及count(*),count(1)和count(列名)的区别?时的应答技巧和注意事项,需要的朋友参考一下 count(*),count(1)在统计的时候不会忽略Null,count(列名)在统计的时候会忽略Null。若列名为主键,count(列名)会比count(1),count(*)快,反之则c

  • 这是一位高级经理问的面试问题。 哪个更快? 我说过,这两者具有相同的执行速度,因为内部的表达式最终应计算为或。在这种情况下,两者的计算结果都为,条件中没有额外的条件指令。因此,两者的执行速度相同,我更喜欢while(1)。 但面试官自信地说:“检查一下你的基础,比要快。”(他不是在考验我的信心) 这是真的吗?

  • Question lintcode: (365) Count 1 in Binary Count how many 1 in binary representation of a 32-bit integer. Example Given 32, return 1 Given 5, return 2 Given 1023, return 9 Challenge If the integer