Выберите следующие N строк после значения

#postgresql

#postgresql

Вопрос:

У меня есть такая таблица

created_on ID версия Причина
2021-01-08 17:13:30 34718 253 принять
2021-01-08 17:13:30 34718 253 принять
2021-01-08 17:13:25 34718 252 Урегулировать
2021-01-08 17:13:25 34718 252 Урегулировать
2021-01-08 17:13:25 34718 252 Урегулировать
2021-01-08 17:11:13 34718 251 Предложение
2021-01-08 17:11:13 34718 251 Предложение
2021-01-08 17:10:26 34718 250 Урегулировать
2021-01-08 17:10:26 34718 250 Урегулировать
2021-01-08 17:10:26 34718 250 Урегулировать
2021-01-08 17:10:24 34718 249 Урегулировать

итак, я хочу выбрать следующие 5 строк после значения «предложение» и установить номер строки для каждого идентификатора

row_id created_on ID версия Причина
6 2021-01-08 17:13:30 34718 253 принять
5 2021-01-08 17:13:30 34718 253 принять
4 2021-01-08 17:13:25 34718 252 Урегулировать
3 2021-01-08 17:13:25 34718 252 Урегулировать
2 2021-01-08 17:13:25 34718 252 Урегулировать
1 2021-01-08 17:11:13 34718 251 Предложение

как это сделать? Спасибо за помощь!

Ответ №1:

Наличие дубликатов целевого объекта несколько усложняет проблему, и порядок убывания также делает это. Далее в тестовых данных возникает вопрос, хотите ли вы 5 после цели во всех случаях только потому, что их всего 5. В любом случае должно быть сделано следующее.

 with test_data( created_on, id, version,reason) as
     ( values ('2021-01-08 17:13:30'::timestamp, 34718, 253, 'accept')
            , ('2021-01-08 17:13:30'::timestamp, 34718, 253, 'accept')
            , ('2021-01-08 17:13:25'::timestamp, 34718, 252, 'Settle')
            , ('2021-01-08 17:13:25'::timestamp, 34718, 252, 'Settle')
            , ('2021-01-08 17:13:25'::timestamp, 34718, 252, 'Settle')
            , ('2021-01-08 17:11:13'::timestamp, 34718, 251, 'offer' )
            , ('2021-01-08 17:11:13'::timestamp, 34718, 251, 'offer' )
            , ('2021-01-08 17:10:26'::timestamp, 34718, 250, 'Settle')
            , ('2021-01-08 17:10:26'::timestamp, 34718, 250, 'Settle')
            , ('2021-01-08 17:10:26'::timestamp, 34718, 250, 'Settle')
            , ('2021-01-08 17:10:24'::timestamp, 34718, 249, 'Settle')
     ) 
select row_number(*) over() row_id, created_on, id, version,reason
  from (select created_on, id, version,reason
          from (select td.*, row_number() over( partition by reason order by created_on desc) rn  
                  from test_data td
                 where created_on >= (select min(created_on) from test_data where reason = 'offer')
              ) s1
          where (reason = 'offer' and rn = 1)
             or (reason != 'offer')
          order by created_on desc
          limit 6
       ) s2;