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

Posted

技术标签:

【中文标题】聚合case语句中sum和count的区别【英文标题】:Difference between sum and count in aggregate case statement 【发布时间】:2020-12-12 16:51:13 【问题描述】:

我在下面有一个查询:

    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,对吗?

谢谢!

【问题讨论】:

正确。 Count 会得到相同的结果。 我不同意,无论它的值是 0 还是 1,Count 仍然会计算行,而 sum 将求和,即如果值如果条件为真三次,那么它将返回 3,而 count 将返回数量行,无论条件是真还是假。 sumcount(*) filter (where e.salary > 10000) .... 相同 【参考方案1】:

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

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

其他一些 dBMS 不支持过滤子句。在这里,我们通过使用CASE WHEN 自己评估表达式来使用变通方法,并使用COUNTSUM 来添加匹配项。以下是一些方法:

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 值。

【讨论】:

【参考方案3】:

大概,员工不在多个部门,所以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) 通常比其他聚合函数贵一点。

【讨论】:

以上是关于聚合case语句中sum和count的区别的主要内容,如果未能解决你的问题,请参考以下文章

sql 聚合语句,count的用法

在 oracle 中的 case 或 decode 语句中使用 sum

聚合函数count里面加条件

Hive 在使用 case 语句和聚合时按列分组出错

hibernate的hql语句不支持 count(case...when ....else..)?

SQL的case when then else end语句的用法