FILTER
What if we want to calculate the percentage of employees that get paid $200,000 per year or more?
We already know how to count the number of employees per company in the employees table.
SELECT count(*) AS count_high_paid
FROM employees
WHERE salary >= 200000;
| count_high_paid BIGINT |
|---|
11 |
To convert that to a percentage, we would need the total count, divide the 2 quantities, and multiple by 100.
SELECT count(*) FROM employees
| count BIGINT |
|---|
38 |
Is there a way to do it all in 1 query, though?
We need a count that just counts all the rows,
and a count that conditionally counts some rows (WHERE salary >= 200000), and to divide those results.
But if we add WHERE salary >= 200000, we can't count the total number of rows in the table anymore.
We can use a style similar to the solution of the Slugging Average challenge.
SELECT
sum(
CASE
WHEN salary >= 200000 THEN 1
ELSE 0
END
) * 100.0 / count(*) AS percent_high_paid
FROM employees;
| percent_high_paid NUMERIC |
|---|
28.9473684210526316 |
This works because sum(1) is equivalent to count(*).
Summing 1 for each row is effectively a count.
Here, we replace 1 with a CASE expression which can return 1 or 0 depending on a condition.
This works, but there is a better way.
Aggregate functions having a FILTER clause which allows you to add a WHERE clause which only applies to that specific aggregate function.
SELECT
count(*) FILTER (WHERE salary >= 200000) * 100.0 / count(*) AS percent_high_paid
FROM employees;
| percent_high_paid NUMERIC |
|---|
28.9473684210526316 |
That's much easier to read and write.