Это может работать лучше из-за выполнения только одного сканирования:
select count(*) as numberofusers,
state
from ( select id, state_id, creationdate,
max(creationdate) over (partition by state_id) - '3 months'::interval as cutoff
from users
) x
join states on states.id = x.state_id
where creationdate > cutoff
group by state
Тем не менее, оно будет прожевать много рабочей памяти при первоначальном агрегировании окон.
Хм, может быть что-тобольше похоже на:
with cutoffs as (
select id, state,
(select max(creationdate)
from users
where users.state_id = states.id) - '3 months'::interval as cutoff
from states)
select count(*) as numberofusers, state
from users
join cutoffs on users.state_id = cutoffs.id
where users.creationdate > cutoff
group by state
Это попытка заставить PostgreSQL правильно сканировать разделы, но это не совсем идеально.Это все еще делает полное сканирование таблицы, но по крайней мере только одно.Функция, возвращающая множество, которая перебирает выходные данные CTE и отправляет результат внешнего запроса внутри цикла, вероятно, будет работать лучше, поскольку она сможет использовать индекс creationdate
для каждого состояния.