Search code examples
sqlpostgresqlconditional-aggregation

Select in Postgres with case


I'm trying to make the following consult:

        Managers | Clerks | Presidents | Analysts | Salesmans
    -------------+---------+--------------+ -----------+-------------

      3            4              1               2               4

So far I manage to do:

select  CASE WHEN lower(job)='salesman' THEN count(job) as "SALESMAN"
 WHEN lower(job)='clerk' THEN count(job)  as "CLERK"
 WHEN lower(job)='manager' THEN count(job)  as "MANAGER"
 WHEN lower(job)='analyst' THEN count(job)  as "ANALYST"
 WHEN lower(job)='president' THEN count(job)  as "PRESIDENT"
from emp
group by job;

But I can't seem to run it, it makes an error:

ERROR: syntax error at or near "as"
LINE 1: ... CASE WHEN lower(job)='salesman' THEN count(job) as "SALESM...

How do I use case in the select to create separate columns?


Solution

  • You need to put the count around the case:

    select count(CASE WHEN lower(job)='salesman' THEN 1 END) as "SALESMAN"
           count(CASE WHEN lower(job)='clerk' THEN 1 END) as "CLERK"
           count(case WHEN lower(job)='manager' THEN 1 END) as "MANAGER"
           count(case WHEN lower(job)='analyst' THEN 1 END)  as "ANALYST"
           count(case WHEN lower(job)='president' THEN 1 END) as "PRESIDENT"
    from emp;
    

    Aggregate functions like count() ignore null values. The CASE expression returns a NULL for values not matching the condition and thus those aren't counted.

    Or simpler using the filter clause:

    select count(*) filter (where lower(job)='salesman') as "SALESMAN"
           count(*) filter (where lower(job)='clerk') as "CLERK"
           count(*) filter (where lower(job)='manager') as "MANAGER"
           count(*) filter (where lower(job)='analyst')  as "ANALYST"
           count(*) filter (where lower(job)='president') as "PRESIDENT"
    from emp;