在任何数据库表上执行"select count(1) from table_name"是什么意思?

124

当我们执行 select count(*) from table_name 时,它会返回行数。

count(1) 做什么?这里的1代表什么?它与 count(*) 相同吗(因为它在执行时给出了相同的结果)?


3
有趣的问题。我也很想知道答案是否取决于实现(例如查询结果在SQL Server和Oracle中是否相同)。 - Jon Schneider
9个回答

139
COUNT函数的参数是一个表达式,该表达式将针对每一行进行评估。COUNT函数返回表达式评估为非空值的行数。( * 是一个特殊的表达式,不进行计算,它仅返回行数。)
表达式有两个附加修饰符: ALL 和 DISTINCT。它们决定是否删除重复项。由于ALL是默认值,因此您的示例与count(ALL 1)相同,这意味着保留重复项。
由于表达式"1"对于每一行都评估为非空,且您未删除重复项,因此 COUNT(1) 应始终返回与 COUNT(*) 相同的数字。

请记住,选择表1中的DISTINCT列1不等于从表1中选择DISTINCT列1的计数。 - Kanagavelu Sugumar
1
+1 为澄清 COUNT(1) 这个令人困惑的语法。现在...如果 "COUNT(1) 应该总是返回与 COUNT() 相同的数字"*, 那么为什么有两种语法形式,只有一个字符不同,却完全相同呢? - datps
1
@datps - 实际上有无限数量的表达式可以得出相同的结果。COUNT('Hello,world!')应该也能正常工作。(我没有尝试过。)那么问题是,既然已经有了无限数量的做同样事情的方法,为什么要创建一个特殊的表达式(*)呢?我不能代表SQL的创作者(他们有很多罪孽要赎),但这可能是为了让人们不必任意选择非空表达式。这会混淆查询作者的意图。“为什么他们写1而不是2?这一定有什么含义!” - Jeffrey L Whitledge
1
谢谢!那么现在的问题应该是,“为什么SQL程序员使用除COUNT(*)之外的语法?”(修辞问题:-)) - datps
@datps 你不能在 COUNT(*) 中使用 DISTINCT。但是你可以使用 SELECT COUNT(DISTINCT 1)...WHERE id=...,它会返回 01(取决于记录是否存在),这比 COUNT(*) 更容易转换为布尔值。 - Caltor
显示剩余3条评论

30

这里有一个链接可以帮助回答您的问题。简而言之:

使用count(*)是正确的写法,count(1)在内部被优化为count(*) -- 因为

a) 计算where 1不为空的行数比
b) 计算所有行数

效率更低


24
在Oracle中,count(*)和count(1)之间有什么区别?
count(*)表示它将计算所有记录,即每个单元格 但是
count(1)表示它将添加一个值为1的伪列,并返回所有记录的计数

9
这类似于“

”之间的区别。
SELECT * FROM table_name and SELECT 1 FROM table_name.  

如果您执行

SELECT 1 FROM table_name

对于表中的每一行,count(*)count(1) 都会给出数字 1。因此,和 count(8) 或者 count(column_name) 相比,它们将提供相同的结果。


5
"count(column_name)"并不完全相同 - 它不会计算该列中包含空值的行数。请参见此处的详细说明:https://dev59.com/nkXRa4cB1Zd3GeqPrWjh - Blorgbeard
嗯,实际上那是针对SQL Server的。我想Oracle可能会有所不同。 - Blorgbeard
按照标准SQL,计数不应使用NULL值,ORacle和SQL Server在这方面应具有相同的行为。 - Thorsten
“类似于SELECT * FROM table_name和SELECT 1 FROM table_name之间的区别。”-- 不完全相同。SELECT 和SELECT 1是不同的。SELECT ()和SELECT (1)会给出相同的结果。 - David Aldridge

7

6
SELECT COUNT(1) from <table name>

应该做与之完全相同的事情。
SELECT COUNT(*)  from <table name>

可能有一些原因,导致它在某些数据库上的表现比SELECT COUNT(*)更好,但我认为这是数据库中的一个错误。

SELECT COUNT(col_name) from <table name>

然而,它有不同的含义,因为它仅计算具有给定列的非空值的行。


3
在Oracle中,我相信这些具有完全相同的含义。

1 是否指代第一列? - dacracot
1
不,1指的是常数1。当你说ORDER BY 1时,它指的是第一列。 - Thilo
我之前也曾经想过这个问题,但是你可以指定任何大于列数的数字,结果仍然相同。因此,它绝对不是列号。 - Nrj
@dacracot:可能会,但我不这么认为。据我所知,Oracle只是在后台将count(1)重写为count(*)。 - Jarod Elliott

2

您可以这样测试:

create table test1(
 id number,
 name varchar2(20)
);

insert into test1 values (1,'abc');
insert into test1 values (1,'abc');

select * from test1;
select count(*) from test1;
select count(1) from test1;
select count(ALL 1) from test1;
select count(DISTINCT 1) from test1;

0

根据不同的人所说,有些人报告称执行 select count(1) from random_table;select count(*) from random_table 运行得更快。其他人则声称它们完全相同。

这个 link 声称两者之间的速度差异是由于 FULL TABLE SCAN 和 FAST FULL SCAN 的原因。


你误解了这个链接。LS想表达的是,COUNT(COLUMN)可以与COUNT(*)相同且更快,但仅当没有任何NOT NULL列被索引而COLUMN被索引且实际上没有空值时。这更像是一个诡计性问题。 - David Aldridge
1
我试图使用链接来证明在某些情况下,COUNT(1)可能比COUNT(*)更快。一些早期的答案声称这两者之间没有区别,而我提供了一个可能的反例。 - Johann Zacharee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接