You are looking for "cross tabulation" or a "pivot table". I added tags.
However:
if I don't know how many types are there, and can't specifically list all cases, how can I achieve it?
Basically, that's impossible in a single SQL query because SQL demands to know the number of result columns at call time. It cannot return a dynamic number of columns on principle.
There are various workarounds with polymorphic types, or with a document type like json
, jsonb
, hstore
or xml
, or return arrays instead of individual columns ...
But to get exactly what you are asking for, an unknown number of dedicated columns, you need a two-step workflow. Like:
- Build the query dynamically (determining the return type).
- Execute it.
Related:
That said, if your case is simple and you deal with a hand full of known types, you can just over-provision. With a faster crosstab()
query, or with simple conditional aggregation like you have it, just more elegant and efficient with the aggregate FILTER
clause:
SELECT count(*) FILTER (WHERE type = 'A') AS type_a
, count(*) FILTER (WHERE type = 'B') AS type_b
, count(*) FILTER (WHERE type = 'C') AS type_c
, count(*) FILTER (WHERE type = 'D') AS type_d
-- that's all folks!
FROM tbl;
Types with no entries report 0
(count()
never returns NULL
) which would be correct anyway.
Does not work for unknown types, obviously.