gpt4 book ai didi

sql - COUNT(*) 与 COUNT(1) 与 COUNT(pk) : which is better?

转载 作者:行者123 更新时间:2023-12-03 04:08:38 27 4
gpt4 key购买 nike

我经常发现这三种变体:

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

但不要对 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 * 上的 * 彼此没有关系,它们是完全不同的东西,它们只是共享一个共同点 token ,即 *

替代语法

事实上,如果不允许将字段命名为与其表名相同的字段,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 字段上有值“Banana”、“Apple”、NULL、“Pears”。这不会计算所有行,它只会产生 3,而不是 4

SELECT count(fruit) FROM fruit

虽然某些 RDBMS 遵循这种原则(为了计算表的行数,它接受表名作为 COUNT 的参数),但这在 Postgresql 中也可以工作(如果任何一个表中都没有 从属 字段)下面两个表,即只要字段名和表名不存在名称冲突即可):

SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id

但是,如果我们在表中添加一个从属字段,那么稍后可能会导致困惑,因为它将计算该字段(可以为空),而不是表行。

为了安全起见,请使用:

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(subscribed.boss_id), COUNT(sublined.*)

因此只需使用以下任一方法即可:

-- 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 - COUNT(*) 与 COUNT(1) 与 COUNT(pk) : which is better?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2710621/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com