Postgres: Filter an aggregation without the WHERE clause
Turns out you can filter aggregations in PostgreSQL outside of the WHERE clause.
During a recent project, we happened upon an interesting use case. We have data that shows a person’s (lid) status (NULL, Active, or Committed) for each fiscal year. We are trying to figure out the prior fiscal year where a person had an “Active” or “Committed” status. Each year a person’s status gets reset and they have to regain their status.
For example:
- For lid 1 fiscal year 2014, there is no prior “Active” or “Committed” year.
- For lid 1 fiscal year 2015, the prior “Active” or “Committed” year is 2014.
- For lid 1 fiscal year 2016, the prior “Active” or “Committed” year is 2014.
- For lid 1 fiscal year 2017, the prior “Active” or “Committed” year is 2016.
In order to solve this we had to use a window function, but we also needed to filter that window function.
Resulting Table
SQL Code:
-- drop the sample table
drop table if exists partition_test;
-- create a sample table
create table partition_test (
lid int,
fiscal_year int,
end_designation varchar
);
-- insert sample data into the sample table
insert into partition_test (lid, fiscal_year, end_designation) VALUES
(1, 2014, 'Active'),
(1, 2015, NULL),
(1, 2016, 'Committed'),
(1, 2017, 'Active'),
(2, 2015, NULL),
(2, 2016, 'Active'),
(3, 2016, 'Active'),
(3, 2017, 'Committed');
-- show data from the sample table
select * from partition_test;
-- show the data from the sample table plus a new column that
select
*,
max(fiscal_year) filter(where partition_test.end_designation IS NOT NULL) over (PARTITION BY lid ORDER BY fiscal_year ASC ROWS BETWEEN UNBOUNDED PRECEDING and 1 PRECEDING) AS fiscal_year_prev_desig
from partition_test;```