Search code examples
sqloraclehierarchyconnect-by

Oracle : Hierarchical Query Connect By


I wrote a Oracle Hierarchical query which will give us Top managers of Particular Employee.

For Example If we have sample Emp and Manager mapping like :

WITH emp_manager_mapping AS (
 select 'A' empId, 'B' managerId,sysdate-100 appliedOn,'Success' status from dual
 union all
 select 'C' empId, 'D' managerId, sysdate-70 appliedOn, 'Success' status from dual
  union all
 select 'B' empId, 'C' managerId, sysdate-50 appliedOn,'Success' status from dual
 )select * from emp_manager_mapping; 

Output is :

A   B   10-SEP-19   Success
C   D   10-OCT-19   Success
B   C   30-OCT-19   Success

After that we applied hierarchical query on this data set what to find who is top manager of Employee id "A" than:

WITH emp_manager_mapping AS (
 select 'A' empId, 'B' managerId,sysdate-100 appliedOn,'Success' status from dual
 union all
 select 'C' empId, 'D' managerId, sysdate-70 appliedOn, 'Success' status from dual
  union all
 select 'B' empId, 'C' managerId, sysdate-50 appliedOn,' Success' status from dual
 ) SELECT
    CONNECT_BY_ROOT ( empid ) AS empid,
    CONNECT_BY_ROOT ( managerid ) AS managerid,
    managerid AS top_manager_id,
    level
FROM
    emp_manager_mapping
WHERE
    CONNECT_BY_ISLEAF = 1 and status = 'Success'
START WITH
    empid = 'A'
CONNECT BY NOCYCLE
    PRIOR managerid = empid;

Than output is:

Value of top_manager_id is D

As per the query it is providing query but not with applied date if we consider the latest applied date also than we have to ignore

C   D   10-OCT-19   Success record.

and i want the final output top_manager id should be "C"

Can any one is helping to find expected result?


Solution

  • Find all the rows in the hierarchy and then order those rows by appliedOn and keep only the latest row:

    Query:

    WITH emp_manager_mapping ( empid, managerid, appliedon, status ) AS (
      select 'A', 'B', sysdate-100,'Success' from dual union all
      select 'C', 'D', sysdate-70, 'Success' from dual union all
      select 'B', 'C', sysdate-50, 'Success' from dual
    )
    SELECT managerid AS top_managerid,
           LEVEL AS depth,
           CONNECT_BY_ROOT ( empid ) AS empid,
           CONNECT_BY_ROOT ( managerid ) AS managerid
    FROM   emp_manager_mapping e
    WHERE  status = 'Success'
    START WITH empid = 'A'
    CONNECT BY NOCYCLE
           PRIOR managerid = empid
    ORDER BY AppliedOn DESC
    FETCH FIRST ROW ONLY;
    

    Output:

    TOP_MANAGERID | DEPTH | EMPID | MANAGERID
    :------------ | ----: | :---- | :--------
    C             |     2 | A     | B        
    

    db<>fiddle here