Вы можете использовать MATCH_RECOGNIZE, чтобы легко сопоставлять шаблоны по нескольким строкам, как в следующем запросе:
WITH test_vals AS (
SELECT 'ABC' as PERSON_ID,TO_DATE('10/4/2018','mm/dd/yyyy') as SERVICE_DATE,'INTAKE' as SERVICE_TYPE FROM DUAL
UNION SELECT 'ABC',TO_DATE('10/8/2018','mm/dd/yyyy'),'INTAKE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('10/19/2018','mm/dd/yyyy'),'DISCHARGE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('10/25/2018','mm/dd/yyyy'),'DISCHARGE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('11/21/2018','mm/dd/yyyy'),'INTAKE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('12/3/2018','mm/dd/yyyy'),'INTAKE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('12/6/2018','mm/dd/yyyy'),'INTAKE' FROM DUAL
UNION SELECT 'ABC',TO_DATE('12/26/2018','mm/dd/yyyy'),'DISCHARGE' FROM DUAL
)
SELECT m.person_id,
m.earliest_intake_date,
m.earliest_discharge_date
FROM test_vals t
match_recognize (
PARTITION BY person_id
ORDER BY service_date, service_type DESC /* Order such that INTAKE comes before DISCHARGE if two items have the same service date */
MEASURES
MIN(service_date) AS earliest_intake_date,
MAX(service_date) AS earliest_discharge_date
ONE ROW PER match
pattern (
intake+ /* Match one or more INTAKE codes, followed by a DISCHARGE */
discharge
)
define
intake AS service_type = 'INTAKE',
discharge AS service_type = 'DISCHARGE'
) m