Från Oracle 12 är det här typen av fråga som MATCH_RECOGNIZE
är avsedd för:
SELECT tran_dt,
alert,
tran_dt
- LAG(CASE alert WHEN 'Yes' THEN tran_dt END, 1, tran_dt)
IGNORE NULLS OVER (ORDER BY tran_dt)
AS days
FROM table_name
MATCH_RECOGNIZE (
ORDER BY tran_dt
MEASURES
CLASSIFIER() AS alert
ALL ROWS PER MATCH
PATTERN ( "Yes" "No"* )
DEFINE
"No" AS tran_dt <= "Yes".tran_dt + INTERVAL '90' DAY
)
Före Oracle 12 kan du använda en rekursiv fråga:
WITH dates (tran_dt, rn) AS (
SELECT tran_dt,
ROW_NUMBER() OVER (ORDER BY tran_dt) AS rn
FROM table_name
),
rolling_dates (tran_dt, alert, rn, days, last_alert) AS (
SELECT tran_dt, 'Yes', rn, 0, tran_dt
FROM dates
WHERE rn = 1
UNION ALL
SELECT d.tran_dt,
CASE
WHEN d.tran_dt <= r.last_alert + INTERVAL '90' DAY
THEN 'No'
ELSE 'Yes'
END,
d.rn,
d.tran_dt - r.last_alert,
CASE
WHEN d.tran_dt <= r.last_alert + INTERVAL '90' DAY
THEN r.last_alert
ELSE d.tran_dt
END
FROM rolling_dates r
INNER JOIN dates d
ON (r.rn + 1 = d.rn)
)
SELECT tran_dt,
alert,
days
FROM rolling_dates;
Båda ger ut:
db<>fiol här