Reputation: 1150
I am attempting to pull details for records using the most recent ROLE_START_DATE. I've tried multiple methods and cant quite get it to work. It always ends up pulling all of the data, rather than specific records.
Base script:
SELECT DISTINCT EMPLOYEE "E.EMPLOYEE #",
LR.DESCRIPTION "Role",
R.ROLE_STATUS "Status",
R.ROLE_START_DATE "Role Start"
FROM EMPLOYEES E
JOIN ROLES R ON E.EMPLOYEE_ID = R.EMPLOYEE_ID
JOIN LU_ROLES LR ON R.ROLE_ID = LR.ROLE_ID
WHERE ROLE_START_DATE <= DATE '2017-12-03'
ORDER BY 1
Results:
Employee # | Role | Status | Role Start
23432 Associate Not Active 04/23/2011
23432 Manager Active 11/2/2012
54334 Analyst Resigned 10/15/2015
12311 Help Desk Not Active 05/12/2014
12311 Analyst Not Active 06/11/2015
12311 Supervisor Active 07/12/2016
Modified to pull just the record with the most current date, but it doesn't work as desired, and gives me the exact same return as above.
SELECT DISTINCT EMPLOYEE "E.EMPLOYEE #",
LR.DESCRIPTION,
R.ROLE_STATUS,
MAX(ROLE_START_DATE)
FROM EMPLOYEES E
JOIN ROLES R ON E.EMPLOYEE_ID = R.EMPLOYEE_ID
JOIN LU_ROLES LR ON R.ROLE_ID = LR.ROLE_ID
WHERE ROLE_START_DATE >= DATE '2017-12-03'
GROUP BY E.EMPLOYEE, LR.DESCRIPTION, R.ROLE_STATUS
ORDER BY 1
What I would like to get:
Employee # | Role | Status | Role Start
23432 Manager Active 11/2/2012
54334 Analyst Resigned 10/15/2015
12311 Supervisor Active 07/12/2016
Any help or advice would be much appreciated.
Thanks in advance!
Upvotes: 0
Views: 64
Reputation: 176264
You could use ROW_NUMBER/RANK
combined with FETCH FIRST ... WITH TIES
(Oracle 12c):
SELECT e.employee, lr.description, r.role_status, r.role_start_date
FROM employees e
JOIN roles r
ON e.employee_id = r.employee_id
JOIN lu_roles lr
ON lr.role_id = r.role_id
WHERE r.role_start_dt >= DATE'2017-12-03'
ORDER BY RANK() OVER (PARITION BY e.employee ORDER BY r.role_start_date DESC)
FETCH FIRST 1 ROW WITH TIES;
Upvotes: 0
Reputation: 12495
The best way to do this is with window functions (what Oracle terms analytic functions). If you want to return ties (employees with multiple roles with the same start date), then use RANK()
or DENSE_RANK()
; if you want an arbitrary role with the most recent start date, use ROW_NUMBER()
:
SELECT employee AS "E.EMPLOYEE #"
, description AS "Role"
, role_status AS "Status"
, role_start_date "Role Start"
FROM (
SELECT e.employee, lr.description, r.role_status, r.role_start_date
, RANK() OVER ( PARITION BY e.employee ORDER BY r.role_start_date DESC ) AS rn
FROM employees e INNER JOIN roles r
ON e.employee_id = r.employee_id
INNER JOIN lu_roles lr
ON lr.role_id = r.role_id
WHERE r.role_start_dt >= DATE'2017-12-03'
) WHERE rn = 1;
Hope this helps.
Upvotes: 1
Reputation: 887
See if this helps -
SELECT * FROM (
SELECT DISTINCT EMPLOYEE "E.EMPLOYEE #",
LR.DESCRIPTION "Role",
R.ROLE_STATUS "Status",
R.ROLE_START_DATE "Role Start",
DENSE_RANK() OVER (PARTITION BY EMPLOYEE ORDER BY ROLE_START_DATE DESC) AS RNK
FROM EMPLOYEES E
JOIN ROLES R ON E.EMPLOYEE_ID = R.EMPLOYEE_ID
JOIN LU_ROLES LR ON R.ROLE_ID = LR.ROLE_ID
WHERE ROLE_START_DATE >= DATE '2017-12-03'
ORDER BY 1
) WHERE RNK = 1
Upvotes: 0