Есть ли в postgresql способ получить приведенный ниже результат, используя раздел или любым другим способом?
last_name year increment partition
Doe 2000 1 1
Doe 2001 2 1
Doe 2002 3 1
Doe 2003 -1 2
Doe 2004 1 3
Doe 2005 2 3
Doe 2006 3 3
Doe 2007 -1 4
Doe 2008 -2 4
SELECT last_name,
year,
increment,
SUM(CASE WHEN increment < 0 THEN 1 ELSE 0 END) OVER (PARTITION BY last_name ORDER BY year) AS partition
FROM your_table
ORDER BY last_name, year;
@kevin.c, это даст другие результаты, чем вы просили в своем вопросе, см. эту демонстрацию, строки за 2007, 2008 годы dbfiddle.uk/TND7pPYa
Кажется, что вы хотите сгруппировать последовательные положительные/отрицательные значения вместе, один из вариантов - использовать разницу между двумя функциями row_number, это создаст раздел, но с неупорядоченными номерами групп.
select *,
row_number() over (partition by last_name order by year) -
row_number() over (partition by last_name,
case when increment>=0 then 1 else 2 end order by year) as prt
from tbl
order by last_name, year
Если вы хотите, чтобы разделы были в порядке (1, 2, 3...), вы можете попробовать другой подход, используя задержку и текущую сумму следующим образом:
select last_name, year, increment,
1 + sum(case when sign(increment) <> sign(pre_inc) then 1 else 0 end) over
(partition by last_name order by year) as prt
from
(
select *,
lag(increment, 1 , increment) over
(partition by last_name order by year) pre_inc
from tbl
) t
order by last_name, year
Посмотреть демо
Если столбец приращения действительно увеличивается за год столбца, он будет помечен как 1; в противном случае он будет помечен как 0. Затем мы группируем последовательные данные, используя «LAG», независимо от того, является ли приращение положительным или отрицательным.
with cte as (
select * ,
row_number() over (partition by last_name order by year) as row_num,
case when increment >= LAG(increment,1,0) over (partition by last_name order by year)
then 1 else 0 end rank_num
from mytable
),
cte2 as (
select *, LAG(rank_num,1,1) over (partition by last_name order by year) as pre
from cte
order by year
)
select last_name, year, increment, 1+sum(case when pre <> rank_num then 1 else 0 end) over
(partition by last_name order by year) as partition
from cte2;
Думаю, что на это невозможно ответить без дополнительных разъяснений.