Eliminate Overlapping Date Ranges based on Employee and their Department with SQL Query
The Start Date is always the first day of the month and the End Date is always the last day of the month.
An Employee can belong to multiple Departments. These employees are all in ONE table, but I split them up to easily display what the expected return is. Also, an employee can have a "dead" period which you can see applied in my third expected return.
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
3904 |
215 |
2022-01-01 |
2022-01-31 |
3904 |
215 |
2022-02-01 |
2022-09-30 |
3904 |
215 |
2022-06-01 |
2022-06-30 |
3904 |
215 |
2022-06-01 |
2022-12-31 |
3904 |
215 |
2022-09-01 |
2022-09-30 |
3904 |
215 |
2022-09-01 |
2022-09-30 |
Expected Return:
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
3904 |
215 |
2022-01-01 |
2022-12-31 |
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
4923 |
629 |
2022-01-01 |
2022-08-31 |
4923 |
629 |
2022-01-01 |
2022-09-30 |
4923 |
629 |
2022-01-01 |
2022-12-31 |
4923 |
629 |
2022-08-01 |
2022-10-31 |
4923 |
629 |
2022-09-01 |
2022-09-30 |
4923 |
629 |
2022-10-01 |
2022-10-31 |
4923 |
629 |
2022-11-01 |
2022-12-31 |
Expected Return:
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
4923 |
629 |
2022-01-01 |
2022-12-31 |
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
8925 |
629 |
2022-01-01 |
2022-04-30 |
8925 |
629 |
2022-02-01 |
2022-03-31 |
8925 |
629 |
2022-08-01 |
2022-10-31 |
8925 |
629 |
2022-11-01 |
2022-12-31 |
Expected Return:
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
8925 |
629 |
2022-01-01 |
2022-04-30 |
8925 |
629 |
2022-08-01 |
2022-12-31 |
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
5877 |
629 |
2022-01-01 |
2022-08-31 |
5877 |
629 |
2022-01-01 |
2022-09-30 |
5877 |
629 |
2022-01-01 |
2022-12-31 |
5877 |
629 |
2022-08-01 |
2022-10-31 |
5877 |
215 |
2022-09-01 |
2022-09-30 |
5877 |
215 |
2022-10-01 |
2022-10-31 |
5877 |
215 |
2022-11-01 |
2022-12-31 |
Expected Return:
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
5877 |
629 |
2022-01-01 |
2022-12-31 |
5877 |
215 |
2022-09-01 |
2022-12-31 |
The below query returns all possible overlapping dates for an EMPLOYEE_ID/DEPARTMENT_ID. I received the expected results.
SELECT A.EMPLOYEE_ID, A.DEPARTMENT_ID, A.START_DATE, A.END_DATE
FROM EMPLOYEES A, EMPLOYEES B
WHERE
A.EMPLOYEE_ID = B.EMPLOYEE_ID AND
A.DEPARTMENT_ID = B.DEPARTMENT_ID AND
(
(A.START_DATE BETWEEN B.START_DATE AND B.END_DATE) OR
(A.END_DATE BETWEEN B.START_DATE AND B.END_DATE) OR
(A.START_DATE < B.START_DATE AND A.END_DATE > B.END_DATE) OR
(A.START_DATE > B.START_DATE AND A.END_DATE < B.END_DATE)
)
ORDER BY A.EMPLOYEE_ID, A.DEPARTMENT_ID, A.START_DATE, A.END_DATE
The following query tries to eliminate the overlapping dates except it doesn't work as intended with my third expected return from above examples.
SELECT A.EMPLOYEE_ID, A.DEPARTMENT_ID, MIN(A.START_DATE), MAX(A.END_DATE)
FROM EMPLOYEES A, EMPLOYEES B
WHERE
A.EMPLOYEE_ID = B.EMPLOYEE_ID AND
A.DEPARTMENT_ID = B.DEPARTMENT_ID AND
(
(A.START_DATE BETWEEN B.START_DATE AND B.END_DATE) OR
(A.END_DATE BETWEEN B.START_DATE AND B.END_DATE) OR
(A.START_DATE < B.START_DATE AND A.END_DATE > B.END_DATE) OR
(A.START_DATE > B.START_DATE AND A.END_DATE < B.END_DATE)
)
GROUP BY A.EMPLOYEE_ID, A.DEPARTMENT_ID
ORDER BY A.EMPLOYEE_ID, A.DEPARTMENT_ID, MIN(A.START_DATE), MAX(A.END_DATE)
EMPLOYEE_ID |
DEPARTMENT_ID |
START_DATE |
END_DATE |
8925 |
629 |
2022-01-01 |
2022-12-31 |