I am working in Oracle Fusion HCM and would like to create a query which pulls an employee's base data such as name, location, etc. We also want to include the managers. Our manager structure is as such so that there's 1 line manager and 1 to n (realistically not more than 3) matrix managers, named 'REVIEWER'.
I have a working code that fetches the data, but it gives issues when there's not exactly 2 managers. When there's 1, it shows the same name twice and if there's 3, there is one that is not shown.
Can anyone help me out on how to fetch the correct manager names without using the MIN/MAX aggregrates? My query is already fetching the correct data, but my pivot clause is not working correctly.
Select DISTINCT *
from
(
SELECT DISTINCT
emplName.DISPLAY_NAME Worker_Name,
INITCAP(loc.LOCATION_NAME) Location_Name,
gra.NAME Grade_Name,
hou.NAME Department_Name,
ass.MANAGER_TYPE Manager_Type,
mgr.DISPLAY_NAME Manager_Name,
REPLACE(ctr.CONTRACT_END_DATE,'4712-12-31') Contract_End_Date,
aa.ASSIGNMENT_NUMBER
FROM
PER_ALL_ASSIGNMENTS_M aa,
PER_ASSIGNMENT_SUPERVISORS_F ass,
PER_PERSON_NAMES_F emplName,
PER_ALL_PEOPLE_F empl,
PER_PERSON_NAMES_F mgr,
HR_ORGANIZATION_UNITS hou,
HR_LOCATIONS_ALL_F_VL loc,
PER_GRADES_F_TL gra,
PER_CONTRACTS_F ctr
WHERE
aa.ASSIGNMENT_ID ( ) = ass.ASSIGNMENT_ID
AND emplName.PERSON_ID = ass.PERSON_ID
AND ass.MANAGER_ID = mgr.PERSON_ID
AND empl.PERSON_ID = ass.PERSON_ID
AND hou.ORGANIZATION_ID = aa.ORGANIZATION_ID
AND loc.LOCATION_ID = aa.LOCATION_ID
AND gra.GRADE_ID = aa.GRADE_ID
AND ctr.CONTRACT_ID = aa.CONTRACT_ID
AND aa.ASSIGNMENT_STATUS_TYPE = 'ACTIVE'
AND to_char(ass.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
AND to_char(aa.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
AND to_char(ctr.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
AND gra.SOURCE_LANG = 'US'
AND gra.NAME in (:p_grade)
AND hou.NAME in (:p_department)
AND INITCAP(loc.LOCATION_NAME) in (:p_location)
AND (ctr.CONTRACT_END_DATE <= (:p_contractenddate)
OR (:p_contractenddate) is null)
) S
Pivot
(
MAX(Manager_Name) Manager1,
MIN(Manager_Name) Manager2
for manager_type in
('LINE_MANAGER' as Line_Manager,
'REVIEWER' as Reviewer
))
Piv
The data regarding managers is recorded in PER_ASSIGNMENT_SUPERVISORS_F ass as follows:
ASSIGNMENT_ID | MANAGER_TYPE | MANAGER_ID |
---|---|---|
0129312 | LINE_MANAGER | 2343943 |
0129312 | REVIEWER | 456756 |
0129312 | REVIEWER | 456334 |
0129312 | REVIEWER | 234324 |
1232232 | LINE_MANAGER | 232242 |
1232232 | REVIEWER | 122312 |
Edit: Table formatting was broken
CodePudding user response:
Use:
Select *
from (
SELECT ass.assignment_id,
ass.person_id,
ass.MANAGER_TYPE Manager_Type,
mgr.DISPLAY_NAME Manager_Name,
ROW_NUMBER() OVER (
PARTITION BY ass.assignment_id, ass.person_id, ass.manager_type
ORDER BY mgr.display_name
) AS rn
FROM PER_ASSIGNMENT_SUPERVISORS_F ass
INNER JOIN PER_PERSON_NAMES_F mgr
ON (ass.MANAGER_ID = mgr.PERSON_ID)
WHERE ass.EFFECTIVE_END_DATE = DATE '4712-12-31'
)
PIVOT (
MAX(Manager_Name)
for (manager_type, rn) in (
('LINE_MANAGER', 1) as Line_Manager,
('REVIEWER', 1) as Reviewer1,
('REVIEWER', 2) as Reviewer2,
('REVIEWER', 3) as Reviewer3
)
)
Then join the rest of the tables to that pivoted query (rather than trying to join first and then pivot).
Which, for the (minimal) sample data:
CREATE TABLE PER_ASSIGNMENT_SUPERVISORS_F (assignment_id, person_id, manager_id, manager_type, effective_end_date) AS
SELECT 1, 1, 2, 'LINE_MANAGER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 1, 1, 3, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 1, 1, 4, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 1, 1, 5, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 2, 2, 3, 'LINE_MANAGER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 2, 2, 4, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 2, 2, 5, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 3, 3, 4, 'LINE_MANAGER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 3, 3, 5, 'REVIEWER', DATE '4712-12-31' FROM DUAL UNION ALL
SELECT 4, 4, 5, 'LINE_MANAGER', DATE '4712-12-31' FROM DUAL;
CREATE TABLE PER_PERSON_NAMES_F (person_id, display_name) AS
SELECT 1, 'Alice' FROM DUAL UNION ALL
SELECT 2, 'Beryl' FROM DUAL UNION ALL
SELECT 3, 'Carol' FROM DUAL UNION ALL
SELECT 4, 'Debra' FROM DUAL UNION ALL
SELECT 5, 'Emily' FROM DUAL;
Outputs:
ASSIGNMENT_ID | PERSON_ID | LINE_MANAGER | REVIEWER1 | REVIEWER2 | REVIEWER3 |
---|---|---|---|---|---|
1 | 1 | Beryl | Carol | Debra | Emily |
2 | 2 | Carol | Debra | Emily | null |
3 | 3 | Debra | Emily | null | null |
4 | 4 | Emily | null | null | null |
CodePudding user response:
Rewrote the query based on MT0s answer. For anyone interested in the end-result:
Select *
from
(
SELECT
emplName.DISPLAY_NAME Worker_Name,
INITCAP(loc.LOCATION_NAME) Location_Name,
gra.NAME Grade_Name,
hou.NAME Department_Name,
ass.MANAGER_TYPE Manager_Type,
mgr.DISPLAY_NAME Manager_Name,
ROW_NUMBER() OVER (
PARTITION BY aa.ASSIGNMENT_NUMBER, ass.assignment_id, ass.person_id, gra.NAME, hou.NAME, ass.manager_type
ORDER BY mgr.display_name
) AS rn,
REPLACE(ctr.CONTRACT_END_DATE,'4712-12-31') Contract_End_Date,
aa.ASSIGNMENT_NUMBER
FROM
PER_ALL_ASSIGNMENTS_F aa
LEFT JOIN PER_ASSIGNMENT_SUPERVISORS_F ass
ON (aa.ASSIGNMENT_ID = ass.ASSIGNMENT_ID
AND to_char(ass.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712')
LEFT JOIN PER_PERSON_NAMES_F_V emplName
ON (ass.PERSON_ID = emplName.PERSON_ID
AND to_char(emplName.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
AND emplName.NAME_TYPE = 'GLOBAL')
LEFT JOIN PER_ALL_PEOPLE_F empl
ON (empl.PERSON_ID = ass.PERSON_ID
AND to_char(empl.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712')
LEFT JOIN PER_PERSON_NAMES_F mgr
ON (mgr.PERSON_ID = ass.MANAGER_ID
AND to_char(mgr.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
AND mgr.NAME_TYPE = 'GLOBAL')
LEFT JOIN HR_ORGANIZATION_UNITS hou
ON (hou.ORGANIZATION_ID = aa.ORGANIZATION_ID
AND to_char(hou.DATE_TO, 'DD/MM/YYYY') = '31/12/4712')
LEFT JOIN HR_LOCATIONS_ALL_F_VL loc
ON (loc.LOCATION_ID = aa.LOCATION_ID
AND to_char(loc.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712')
LEFT JOIN PER_GRADES_F_TL gra
ON (gra.GRADE_ID = aa.GRADE_ID
AND gra.LANGUAGE = 'US'
AND to_char(gra.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712')
LEFT JOIN PER_CONTRACTS_F ctr
ON (ctr.CONTRACT_ID = aa.CONTRACT_ID
AND to_char(ctr.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712')
WHERE 1=1
AND aa.ASSIGNMENT_STATUS_TYPE = 'ACTIVE'
AND to_char(aa.EFFECTIVE_END_DATE, 'DD/MM/YYYY') = '31/12/4712'
-- PARAMETERS
AND gra.NAME in (:p_grade)
AND hou.NAME in (:p_department)
AND INITCAP(loc.LOCATION_NAME) in (:p_location)
AND (ctr.CONTRACT_END_DATE <= (:p_contractenddate)
OR (:p_contractenddate) is null)
) S
Pivot
(
MAX(Manager_Name)
for (manager_type, rn) in (
('LINE_MANAGER', 1) as Line_Manager,
('REVIEWER', 1) as Reviewer1,
('REVIEWER', 2) as Reviewer2,
('REVIEWER', 3) as Reviewer3
))
Piv