Given the current job code (e.g., DA123-2) and the previous job code (e.g., DA123-1), calculate the tenure starting from the date of the previous job code (ignoring anything after the hyphen in the job code).
In the example provided, the employee’s job role changed four times: ITW124 -> DA123 -> DA123-1 -> DA123-2. Since the last three job codes are the same before the hyphen, we should consider the last job role change as of March 23, 2024.
Please see the sample data tables below
We cannot use the Analytical functions(LAG/LEAD) as it is not supported. I tried with Previous dates on the Job_ID but no luck.
From Oracle 12, you can use MATCH_RECOGNIZE
to perform row-by-row pattern matching and find the earliest date from the latest roles where the stem of the job-code is unchanged:
WITH emp_jobs (eid, changedate, job_code) AS (
SELECT e.eid,
e.changedate,
REGEXP_REPLACE(j.job_code, '-.*$')
FROM employee e
INNER JOIN job j
ON e.job_id = j.job_id
)
SELECT eid,
TRUNC(SYSDATE) - changedate AS tenure
FROM emp_jobs
MATCH_RECOGNIZE(
PARTITION BY eid
ORDER BY changedate DESC
MEASURES
LAST(changedate) AS changedate
PATTERN ( ^ same_job+ )
DEFINE same_job AS FIRST(job_code) = job_code
)
If you cannot use MATCH_RECOGNIZE
or analytic functions then you can use:
WITH emp_jobs (eid, changedate, job_code) AS (
SELECT e.eid,
e.changedate,
REGEXP_REPLACE(j.job_code, '-.*$')
FROM employee e
INNER JOIN job j
ON e.job_id = j.job_id
)
SELECT eid,
TRUNC(SYSDATE) - MIN(changedate) AS tenure
FROM emp_jobs ej
WHERE NOT EXISTS (
SELECT 1
FROM emp_jobs x
WHERE ej.eid = x.eid
AND ej.job_code != x.job_code
AND ej.changedate < x.changedate
)
GROUP BY eid
Which, for the sample data:
CREATE TABLE employee (eid, job_id, changedate) AS
SELECT 123, 1001, TRUNC(SYSDATE) - 0 FROM DUAL UNION ALL
SELECT 123, 2002, TRUNC(SYSDATE) - 37 FROM DUAL UNION ALL
SELECT 123, 3003, TRUNC(SYSDATE) - 110 FROM DUAL UNION ALL
SELECT 123, 4004, TRUNC(SYSDATE) - 150 FROM DUAL UNION ALL
SELECT 123, 3003, TRUNC(SYSDATE) - 300 FROM DUAL;
CREATE TABLE job (job_id, job_code) AS
SELECT 1001, 'DA123-2' FROM DUAL UNION ALL
SELECT 2002, 'DA123-1' FROM DUAL UNION ALL
SELECT 3003, 'DA123' FROM DUAL UNION ALL
SELECT 4004, 'ITW124' FROM DUAL;
Both output:
EID | TENURE |
---|---|
123 | 110 |