'Optimize a max() aggregate that works for "no rows", too
I have a query that I am trying to optimize for PostgreSQL 9.2:
select coalesce(max(id),0) as m from tbl
It takes for forever to run, so I figured I could rewrite it as
select id from tbl order by id desc limit 1
except it needs to return 0 if there are no rows in the table. I've tried a few combinations of case statements, but they don't seem to work. Any suggestions?
Plan for an empty table:
Aggregate (cost=11.25..11.26 rows=1 width=4)
-> Seq Scan on tbl (cost=0.00..11.00 rows=100 width=4)
The cost is 58k with a table with 1,190,000 rows, same execution plan though.
Solution 1:[1]
except it needs to return 0 if there are no rows in the table
SELECT COALESCE(max(id), 0) FROM tbl;
This works because max() - like all aggregate functions - always returns a row, even if there are no rows in the table.
Fine point: this also returns 0 if all existing rows of tbl have id IS NULL.
See:
When no row can be returned, wrap the SELECT it in a subquery:
SELECT COALESCE((SELECT max(id) FROM tbl), 0); -- not necessary for max()
The key to performance is an index on tbl.id Could be a primary (or unique) key constraint, which is implemented using a unique index on the column. Or a plain b-tree index:
CREATE index foo on tbl(id)
See:
Solution 2:[2]
Maybe this:
select
case
when (select id from tbl limit 1) is null then 0
else (select id from tbl order by id desc limit 1)
end;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
