Есть ли способ разбить по инкрементной серии в Postgresql?

Есть ли в 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

Думаю, что на это невозможно ответить без дополнительных разъяснений.

Laurenz Albe 20.02.2023 03:28
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
0
1
65
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий
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

ahmed 20.02.2023 18:27

Кажется, что вы хотите сгруппировать последовательные положительные/отрицательные значения вместе, один из вариантов - использовать разницу между двумя функциями 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;

Другие вопросы по теме