Если я правильно понимаю, вы хотели бы подсчитать количество различных идентификаторов элементов до каждой строки (по дате) и вернуть все строки, в которых количество равно трем.
Если бы Postgres поддерживал это, вы могли бы использовать:
select t.*
from (select t.*,
count(*) filter (where id = min_id) over (order by date desc) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date desc) as min_id
from t
) t
) t
where cnt_itemid <= 3;
Увы, Postgres не поддерживает COUNT(DISTINCT)
в качестве оконной функции. Но вы можете рассчитать его, используя DENSE_RANK()
:
select t.*
from (select t.*,
count(*) over (filter where id = min_id) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date) as min_id
from t
) t
) t
where cnt_itemid <= 3;
Однако это возвращает все самые последние строки до 4-го элемента, поэтому у него есть дополнительные строки.
Чтобы получить четыре строки, вам нужна первая, где идентификатор элемента равен 3. Один из методов:
select t.*
from (select t.*, min(id) filter (where cnt_itemid = 3) over () as min_cnt_itemid_3
from (select t.*,
count(*) filter (where id = min_id) over (order by date desc) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date desc) as min_id
from t
) t
) t
) t
where id <= min_cnt_itemid_3;
Вы также можете сделать это, указав первое вхождение третьего элемента, а затем выбрав все строки до этой строки:
select t.*
from t join
(select itemid, min(max_date) over () as min_max_date
from (select t.itemid, max(date) as max_date
from t
group by t.itemid
order by max(t.date) desc
limit 3
) t
) tt
on t.itemid = tt.itemid and t.date >= tt.min_max_date;
Эта скрипта показывает каждый из них.
person
Gordon Linoff
schedule
25.01.2021