聚合case语句中sum和count的区别

问题描述 投票:0回答:4

我有一个疑问如下:

    SELECT 
       d.name, 
      SUM(CASE WHEN e.salary > 100000 THEN 1 ELSE 0 END)
        / COUNT(DISTINCT e.id)
        AS pct_above_100k,
      COUNT(DISTINCT e.id) AS c
FROM employees e JOIN departments d ON e.department_id = d.id
GROUP BY 1
HAVING COUNT(*) > 10
ORDER BY 2 DESC

我这里使用的是 sum,但是如果我使用 count 会有什么不同吗?

我知道 count 计算某个值存在的次数,sum 则将实际值相加,但这里因为我的条件是如果工资 > 100000,它无论如何都会将其视为 1,对吗?

谢谢!

sql postgresql presto
4个回答
3
投票

我们使用过滤子句有条件地进行计数:

COUNT(*) FILTER (WHERE e.salary > 100000)

其他一些 dBMS 不支持过滤器子句。在这里,我们使用解决方法,通过使用

CASE WHEN
自行计算表达式,并使用
COUNT
SUM
来添加匹配项。以下是一些方法可以做到这一点:

SUM(CASE WHEN e.salary > 100000 THEN 1 ELSE 0 END)
COUNT(CASE WHEN e.salary > 100000 THEN 1 ELSE NULL END)
COUNT(CASE WHEN e.salary > 100000 THEN 1 END)
COUNT(CASE WHEN e.salary > 100000 THEN 'count this' END)

由于 PostgreSQL 确实支持过滤子句,因此您应该使用

COUNT(*) FILTER (...)


2
投票

如果您只是将

sum
替换为
count
,您会得到不同的结果,因为 0 和 1 一样重要。

最优雅的写法是

FILTER
子句,正如其他人提到的,但你也可以这样做:

count(CASE WHEN e.salary > 100000 THEN 0 END)

这可行,因为(大多数)聚合函数会忽略 NULL 值。


2
投票

想必员工并不在多个部门,所以

count(distinct)
是不必要的。

这意味着代码可以更简单地写为:

  AVG(CASE WHEN e.salary > 100000 THEN 1 ELSE 0 END) AS pct_above_100k,

或者:

  AVG( (e.salary > 100000)::int ) AS pct_above_100k,

这些将比替代方案更有效,因为

COUNT(DISTINCT)
通常比其他聚合函数更昂贵。


0
投票

我认为你可以将其简化为: SUM(e.工资 > 100000) 虽然我不确定为什么会这样。

而如果您使用 COUNT,则必须使用 WHERE 作为条件。

© www.soinside.com 2019 - 2024. All rights reserved.