gpt4 book ai didi

sql - sum() 与 count()

转载 作者:行者123 更新时间:2023-11-29 11:14:44 25 4
gpt4 key购买 nike

考虑一个在 PostgreSQL 中实现的投票系统,其中每个用户都可以对“foo”投票赞成或反对。有一个foo表存储所有的“foo信息”,还有一个votes表存储user_idfoo_idvote,其中 vote 为 +1 或 -1。

要获得每个 foo 的投票计数,可以使用以下查询:

SELECT sum(vote) FROM votes WHERE foo.foo_id = votes.foo_id;

但是,下面的方法同样有效:

(SELECT count(vote) FROM votes 
WHERE foo.foo_id = votes.foo_id
AND votes.vote = 1)
- (SELECT count(vote) FROM votes
WHERE foo.foo_id = votes.foo_id
AND votes.vote = (-1))

我目前在 votes.foo_id 上有一个索引。

哪种方法更有效? (换句话说,哪个会跑得更快?)我对特定于 PostgreSQL 的答案和一般的 SQL 答案都感兴趣。

编辑

很多答案都考虑到了 vote 为 null 的情况。我忘了提到投票列上有一个 NOT NULL 约束。

此外,许多人指出第一个更容易阅读。是的,这绝对是真的,如果一位同事写了第二个,除非有性能需要,否则我会气得发狂。尽管如此,问题仍然在于两者的表现。 (从技术上讲,如果第一个查询方式慢,那么编写第二个查询就不算犯罪。)

最佳答案

当然,第一个示例更快、更简单且更易于阅读。甚至在得到 slapped with aquatic creatures 之前就应该很明显了.虽然 sum()count() 稍微贵一点,但更重要的是第二个示例需要两次扫描。

但也有一个实际差异:sum() 可以返回 NULL,其中 count()没有。我引用 manual on aggregate functions :

It should be noted that except for count, these functions return a null value when no rows are selected. In particular, sum of no rows returns null, not zero as one might expect,

由于您似乎在性能优化方面存在弱点,这里有一个您可能会喜欢的细节:count(*) is slightly faster than count(vote )。仅当 vote 为 NOT NULL 时等效。使用 EXPLAIN ANALYZE 测试性能.

仔细观察

两个查询都是语法废话,单独存在。只有从更大查询的 SELECT 列表中复制它们才有意义,例如:

SELECT *, (SELECT sum(vote) FROM votes WHERE votes.foo_id = foo.foo_id)
FROM foo;

这里的重点是相关子查询 - 如果您在查询中只读取一小部分 votes,这可能没问题。我们会看到额外的 WHERE 条件,您应该有匹配的索引。

在 Postgres 9.3 或更高版本中,替代的、更清晰的、100% 等效的解决方案是使用 LEFT JOIN LATERAL ... ON true:

SELECT *
FROM foo f
LEFT JOIN LATERAL (
SELECT sum(vote) FROM votes WHERE foo_id = f.foo_id
) v ON true;

通常性能相似。详情:

但是,在从表 votes 中读取大部分或全部时,这会(快)得多:

SELECT f.*, v.score
FROM foo f
JOIN (
SELECT foo_id, sum(vote) AS score
FROM votes
GROUP BY 1
) v USING (foo_id);

首先聚合子查询中的值,然后连接到结果。
关于使用:

关于sql - sum() 与 count(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14998225/

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