简体   繁体   中英

Hierarchical query using oracle SQL

We have following table to query data from,

EMPLOYEE_ABSENCE_TAB

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.

  • absence_days : number of absence days = sum(to_date - from_date)
  • from_date : first from_date where absence_continuation is NULL
  • to_date : last to_date connect by prior absence_id = absence_continuation

Expected Outcome

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM