I am building a blog and i have a problem. There should be some sticky posts. All i want is to get first the sticky posts and then the rest.
One query that works is
select * from
(
(select *,true as st from blog where "stickyUntil" > current_timestamp)
UNION all
(SELECT *,false as st from blog where "stickyUntil" < current_timestamp or "stickyUntil" is null )
) q
order by st desc, "stickyUntil" DESC ,publish DESC OFFEST x LIMIT z
Another simpler query that workz is
select * from blog order by case when "stickyUntil" > current_timestamp then "stickyUntil" end desc nulls last, publish desc;
But this would force 200.000 rows to be sorted in memory not very fast..
Is there a way to optimize it ??
Would it be better to use two separate queries ?
Thanks
I would go with a CASE statement to avoid two passes of the table:
Postgres supports creating an INDEX on a computed field which would help here but there is a restriction:
So you cannot index the st calculation. If the calculation of st does not need to be too accurate another option is to add the st field to the table:
INDEX st as a regular column:
And periodically run:
but having a polling process doing an update is much less attractive than a straight up query. This would only make sense if your query is really slow or there are a lot of reads of the blog table.