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.

© 2022 Andrew Carlson. All rights reserved.