We have following table to query data from,
emp_id | absence_id | from_date | to_date | absence_continuation |
---|---|---|---|---|
100 | 1 | 01/01/2022 | 03/01/2022 | |
100 | 2 | 01/02/2022 | 05/02/2022 | 1 |
200 | 3 | 01/01/2022 | 07/01/2022 | |
200 | 4 | 10/01/2022 | 14/01/2022 | 3 |
200 | 5 | 16/01/2022 | 20/01/2022 | 4 |
300 | 6 | 01/01/2022 | 14/01/2022 |
We need to connect data hierarchically based on the following logic. Output should be emp_id, absence_days, from_date and to_date.
emp_id | absence_days | from_date | to_date |
---|---|---|---|
100 | 8 | 01/01/2022 | 05/02/2022 |
200 | 17 | 01/01/2022 | 20/01/2022 |
300 | 14 | 01/01/2022 | 14/01/2022 |
I tried hierarchical but could able to come up with working solution. How can this be achieved using hierarchical query in Oracle SQL?
You don't need to consider the hierarchy in the data (assuming that there are no overlaps); you just need to aggregate:
SELECT emp_id,
SUM(to_date - from_date + 1) AS absence_days,
MIN(from_date) AS from_date,
MAX(to_date) AS to_date
FROM EMPLOYEE_ABSENCE_TAB
GROUP BY emp_id
Which, for the sample data:
CREATE TABLE EMPLOYEE_ABSENCE_TAB
(emp_id, absence_id, from_date, to_date, absence_continuation) AS
SELECT 100, 1, DATE '2022-01-01', DATE '2022-01-03', NULL FROM DUAL UNION ALL
SELECT 100, 2, DATE '2022-02-01', DATE '2022-02-05', 1 FROM DUAL UNION ALL
SELECT 200, 3, DATE '2022-01-01', DATE '2022-01-07', NULL FROM DUAL UNION ALL
SELECT 200, 4, DATE '2022-01-10', DATE '2022-01-14', 3 FROM DUAL UNION ALL
SELECT 200, 5, DATE '2022-01-16', DATE '2022-01-20', 4 FROM DUAL UNION ALL
SELECT 300, 6, DATE '2022-01-01', DATE '2022-01-14', NULL FROM DUAL;
Outputs:
EMP_ID ABSENCE_DAYS FROM_DATE TO_DATE 100 8 2022-01-01 00:00:00 2022-02-05 00:00:00 200 17 2022-01-01 00:00:00 2022-01-20 00:00:00 300 14 2022-01-01 00:00:00 2022-01-14 00:00:00
If you did want to consider the hierarchy and get the duration of each absence (and not the total absences per employee) then you can use:
SELECT emp_id,
absence_id,
SUM(to_date - from_date + 1) AS absence_days,
MIN(from_date) AS from_date,
MAX(to_date) AS to_date
FROM (
SELECT emp_id,
CONNECT_BY_ROOT absence_id AS absence_id,
to_date - from_date + 1 AS absence_days,
from_date,
to_date
FROM EMPLOYEE_ABSENCE_TAB
START WITH absence_continuation IS NULL
CONNECT BY PRIOR absence_id = absence_continuation
)
GROUP BY
emp_id,
absence_id
Which outputs the same (with an additional absence_id
column for the id
of the first part of the absence) for your sample data as you only have a single absence for each employee; if you had more absences then it would aggregate each absence separately.
db<>fiddle here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.