Оракул - разрыв и остров на двух столбцах - PullRequest
0 голосов
/ 01 февраля 2019

Исходные данные:

SELECT RCMOUVNT.MATRICULE, RCMOUVNT.DATENT, RCMOUVNT.DATOUT FROM RCMOUVNT
WHERE RCMOUVNT.MATRICULE = '81123404' order by DATENT asc;

MATRICULE   DATENT      DATOUT
81123404    04/09/17    30/11/17
81123404    01/12/17    31/07/18
81123404    01/02/19    31/01/20

Ожидаемый результат с использованием SQL:

MATRICULE   DATENT      DATOUT
81123404    04/09/17    31/07/18
81123404    01/02/19    31/01/20

Я знаю, что это проблема "пробела и острова", но я не нашел ответа.

1 Ответ

0 голосов
/ 01 февраля 2019

Одно из возможных решений с использованием трех шагов

  • найти отдельные группы записей (каждая точка останова получает новый GRP_ID).Обратите внимание, что вы должны добавить 1 день к DATAOUT из предыдущей строки перед совпадением с DATENT, чтобы получить свой логик.Также в первом ряду автоматически получают группу с помощью NVL.

  • заполнения NULL в группах (второй подзапрос) - используйте LAST_VALUE

  • агрегат на группу (стандартный GROUP BY) - в третьем запросе используются GROUP BY и MIN соотв.MAX чтобы получить результат.

.

with q1   as (
select 
  MATRICULE,
  DATENT,
  DATOUT, 
  case when (nvl(lag(DATOUT +1) over (partition by MATRICULE order by DATENT),DATE'2500-01-01') <> DATENT) then 
     row_number() over (partition by MATRICULE order by DATENT) end grp
from RCMOUVNT 
), q2 as (
select 
  MATRICULE,
  DATENT,
  DATOUT,
  grp,
  last_value(grp ignore nulls) over (partition by MATRICULE order by DATENT) as grp2
from q1
)   
select 
    MATRICULE,  
    min(DATENT) DATENT, 
    max(DATOUT) DATOUT
from q2
group by MATRICULE, grp2
order by 1

 MATRICULE DATENT              DATOUT             
---------- ------------------- -------------------
  81123404 04.09.2017 00:00:00 31.07.2018 00:00:00
  81123404 01.02.2019 00:00:00 31.01.2020 00:00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...