You can take advantage of the ROW_NUMBER
analytical function to generate a unique, sequential number for each of the records (we'll assign that number to the dates in ascending order).
Then, you group the dates by difference between the date and the generated number - the consecutive dates will have the same difference:
Date Number Difference 01-APR-05 1 1 -- MIN(date_val) in group with diff. = 1 02-APR-05 2 1 03-APR-05 3 1 04-APR-05 4 1 05-APR-05 5 1 06-APR-05 6 1 07-APR-05 7 1 -- MAX(date_val) in group with diff. = 1 11-APR-05 8 3 -- MIN(date_val) in group with diff. = 3 12-APR-05 9 3 13-APR-05 10 3 14-APR-05 11 3 15-APR-05 12 3 16-APR-05 13 3 -- MAX(date_val) in group with diff. = 3
Finally, you select the minimal and maximal date in each of the groups to get the beginning and ending of each range.
Here's the query:
SELECT
MIN(date_val) start_date,
MAX(date_val) end_date
FROM (
SELECT
date_val,
row_number() OVER (ORDER BY date_val) AS rn
FROM date_tab
)
GROUP BY date_val - rn
ORDER BY 1
;
Output:
START_DATE END_DATE ------------ ---------- 01-04-2005 07-04-2005 11-04-2005 16-04-2005 19-04-2005 24-04-2005 26-04-2005 30-04-2005
You can check how that works on SQLFidlle: Dates ranges example