A similar question has been asked before but I've been having trouble adapting those answers to my question.
I want to find rows on consecutive dates, where another column has the same value, and return that as a single date range.
I have tried using OVER
and PARTITION BY
along with ROW_NUMBER() to get the results I need, but I'm not familiar enough with those concepts to figure out the correct output.
The system is Microsoft SQL Server 2014.
Given:
CREATE TABLE EXCEPTIONS
(
ID NUMERIC(18) NOT NULL,
DATE DATE NOT NULL,
TYPE VARCHAR(20) NOT NULL,
VALUE VARCHAR(20),
);
and the data:
INSERT INTO EXCEPTIONS VALUES
(17482, '2016-08-24', 'PRESSURE_EXCEPTION', 'Over'),
(17482, '2016-08-25', 'PRESSURE_EXCEPTION', 'Over'),
(17482, '2016-08-26', 'PRESSURE_EXCEPTION', 'Over'),
(17482, '2016-09-04', 'PRESSURE_EXCEPTION', 'Over'),
(17482, '2016-09-05', 'PRESSURE_EXCEPTION', 'Over'),
(17482, '2016-09-16', 'PRESSURE_EXCEPTION', 'Under'),
(17482, '2016-09-17', 'PRESSURE_EXCEPTION', 'Under'),
(17482, '2016-09-23', 'PRESSURE_EXCEPTION', 'Under'),
(17482, '2016-09-24', 'PRESSURE_EXCEPTION', 'Under'),
(17482, '2016-09-25', 'PRESSURE_EXCEPTION', 'Under'),
(17482, '2016-09-27', 'VOLUME_EXCEPTION', 'Low'),
(17482, '2016-09-28', 'VOLUME_EXCEPTION', 'Low')
The result of this query should be something like
StartDate | EndDate | Type | Value
2016-08-24 | 2016-08-26 | 'PRESSURE_EXCEPTION' | 'Over'
2016-09-04 | 2016-09-05 | 'PRESSURE_EXCEPTION' | 'Over'
2016-09-16 | 2016-09-17 | 'PRESSURE_EXCEPTION' | 'Under'
2016-09-23 | 2016-09-25 | 'PRESSURE_EXCEPTION' | 'Under'
2016-09-27 | 2016-09-28 | 'VOLUME_EXCEPTION' | 'Low'
SQLFiddle available with more data
Best Answer
This is a 'Gaps and Islands' problem. I took this example and tweaked it for your situation.
The OVER/PARTITION logic is basically assigning each row to a 'group' so you can pick out the
MIN
andMAX
from each group. If you un-comment theselect * from mycte
(I added an order by date) and run the script from that part to the top, you'll see that each row gets assigned to a group.Look at the first group of rows assigned to '2016-08-23'. The
ROW_NUMBER
for date '2016-08-24' is 1, so theDATEADD
subtracts 1 from '2016-08-24' to put that row in group '2016-08-23'. TheROW_NUMBER
for date '2016-08-25' is 2, so theDATEADD
subtracts 2 from '2016-08-25' to put it in the same group as row number 1 and so on.Now, it's just a matter of pulling the
MIN
andMAX
from each group.