聚合 case 语句中 sum 和 count 的区别
Difference between sum and count in aggregate case statement
我有一个查询如下:
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
我这里用的是求和,如果用计数会有什么不同吗?
我知道 count 计算一个值存在的次数,而 sum 将实际值相加,但这里因为我的条件是如果薪水 > 100000,它会把它看成 1 对吗?
谢谢!
我们使用过滤子句有条件地计数:
COUNT(*) FILTER (WHERE e.salary > 100000)
其他一些 dBMS 不支持 filter 子句。在这里,我们通过使用 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 (...)
。
如果您只是将 sum
替换为 count
,您会得到不同的结果,因为 0 与 1 一样重要。
最优雅的写法是 FILTER
子句,正如其他人提到的,但您也可以这样做:
count(CASE WHEN e.salary > 100000 THEN 0 END)
这可行,因为(大多数)聚合函数会忽略 NULL 值。
大概员工不在多个部门,所以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)
通常比其他聚合函数贵一点。
我有一个查询如下:
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
我这里用的是求和,如果用计数会有什么不同吗?
我知道 count 计算一个值存在的次数,而 sum 将实际值相加,但这里因为我的条件是如果薪水 > 100000,它会把它看成 1 对吗?
谢谢!
我们使用过滤子句有条件地计数:
COUNT(*) FILTER (WHERE e.salary > 100000)
其他一些 dBMS 不支持 filter 子句。在这里,我们通过使用 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 (...)
。
如果您只是将 sum
替换为 count
,您会得到不同的结果,因为 0 与 1 一样重要。
最优雅的写法是 FILTER
子句,正如其他人提到的,但您也可以这样做:
count(CASE WHEN e.salary > 100000 THEN 0 END)
这可行,因为(大多数)聚合函数会忽略 NULL 值。
大概员工不在多个部门,所以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)
通常比其他聚合函数贵一点。