How PostgreSQL's Aggregate FILTER Will Spoil You
Using PostgreSQL will definitely spoil you. I recently had to use another database and found, to my chagrin, that aggregate filters were not included in their implementation of Structured Query Language. Specifically, there was no FILTER clause available.
FILTER?
To illustrate my dependency, let me start with some simple data.
demo=# create table z (a int, b int, c int);
CREATE TABLE
demo=# insert into z values (1,10,100),(2,20,200),(3,30,300),(4,40,400);
INSERT 0 4
demo=# select a,b,c from z;
a | b | c
---+----+-----
1 | 10 | 100
2 | 20 | 200
3 | 30 | 300
4 | 40 | 400
(4 rows)
demo=#
CREATE TABLE
demo=# insert into z values (1,10,100),(2,20,200),(3,30,300),(4,40,400);
INSERT 0 4
demo=# select a,b,c from z;
a | b | c
---+----+-----
1 | 10 | 100
2 | 20 | 200
3 | 30 | 300
4 | 40 | 400
(4 rows)
demo=#
If I wanted the overall number of rows, I could use a simple COUNT(*). If I wanted an overall number of rows where one of the columns was of a certain value, I could add the logic for getting those rows to the WHERE clause.
What if I wanted both? Do I need two queries to do the work separately? Maybe a materialized view or a CTE (Common Table Expression)? Will I need a Window Function?
FILTER!
PostgreSQL provides the ability to do what is needed with one SELECT statement.
demo=# select count(*) as all_rows,
demo-# count(*) FILTER (where b > 11) as b_gt_11
demo-# from z;
all_rows | b_gt_11
----------+---------
4 | 3
(1 row)
demo=#
The above SELECT statement asks for two columns of data. The first asks for a count of all rows.
The second requests a count of all rows where the b column's value exceeds 11. The FILTER defines the rows of interest.
Long-time SQL writers will immediately spot how handy the ability to filter rows this way is.
Sadly, the database I had to use did not offer the ability to do this. What should have been a simple query became a detour into the bumpy backroads of finding another way to get the answer.
Comments
Post a Comment