À partir d'Oracle 12, c'est le type de requête que MATCH_RECOGNIZE
est destiné à :
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
)
Avant Oracle 12, vous pouvez utiliser une requête récursive :
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;
Les deux génèrent :
db<>violon ici