Forum Discussion
TCatron18
Dec 12, 2024Copper Contributor
Capturing Latest Effective Date of Current Instance of Position
I am having issues trying to formulate a JOIN statement within my query that will provide the values that I am needing for all employees. Specifically, situations where an employee held the position ...
TCatron18
Dec 16, 2024Copper Contributor
Correct.
But if B had a change to their position for 8849/3 on say '2024/11/20' we still want that '2024/8/26' date.
rodgerkong
Dec 18, 2024Iron Contributor
If my understanding was correct, the following steps will work. It's a little complicated.
- Identify the row at the starting point of each successive position/assignment.
- Use Recursed Query to pass the first EFFECT_DATE to the end row of each successive position/assignment.
- GROUPING by EMPLOYEE, S_DATE(start_date), POSTION and ASSIGNMENT to aggregated the successive position/assignment to one row. So far, we have start_date and end_date for each position assigned to each employee.
- GROUPING by EMPLOYEE, POSTION and ASSIGNMENT, will get final result.
Code is here ( base on your sample data )
CREATE TABLE #W
(
EMPLOYEE VARCHAR(10),
R_POSITION INT,
WORK_ASSIGNMNT INT
);
INSERT INTO #W
VALUES
('A', 7059, 5)
,('B', 8849, 3);
CREATE TABLE #EP
(
EMPLOYEE VARCHAR(10),
R_POSITION INT,
WORK_ASSIGNMNT INT,
EFFECT_DATE DATE,
END_DATE DATE
);
INSERT INTO #EP
VALUES
('A', 7059, 5, '2022/9/19', '2022/9/24'),
('A', 7059, 5, '2022/9/25', '2023/6/17'),
('A', 7059, 5, '2023/6/18', '2024/1/13'),
('A', 7059, 5, '2024/1/14', '2024/2/10'),
('A', 7059, 5, '2024/2/11', '2024/3/8'),
('A', 7059, 5, '2024/3/9', '2024/3/9'),
('A', 7059, 5, '2024/3/10', '2024/4/20'),
('A', 7059, 5, '2024/4/21', '2099/12/31'),
('B', 23455, 3, '2022/6/27', '2022/6/29'),
('B', 22773, 3, '2022/6/30', '2022/8/26'),
('B', 22773, 3, '2022/8/27', '2022/8/27'),
('B', 22773, 3, '2022/8/28', '2022/10/22'),
('B', 22773, 3, '2022/10/23', '2022/12/27'),
('B', 22773, 3, '2022/12/28', '2023/6/17'),
('B', 22773, 3, '2023/6/18', '2023/10/15'),
('B', 8849, 3, '2023/10/16', '2024/2/10'),
('B', 26041, 3, '2024/2/11', '2024/3/9'),
('B', 26041, 3, '2024/3/10', '2024/4/20'),
('B', 26041, 3, '2024/4/21', '2024/8/25'),
('B', 8849, 3, '2024/8/26', '2099/12/31');
WITH CTE_PRE -- Prepare a dataset for next step of recurse, and filter the rows that should be focused.
AS
(
SELECT EP.*
--Find the rows that is the start point of each position/assignment, mark them with HAS_LAG = 0
,IIF(DATEADD(DAY, 1, LAG(EP.END_DATE, 1, '1900-01-01') OVER (PARTITION BY EP.EMPLOYEE, EP.R_POSITION, EP.WORK_ASSIGNMNT ORDER BY EP.EFFECT_DATE))=EP.EFFECT_DATE, 1, 0) AS HAS_LAG
FROM #EP AS EP
INNER JOIN (SELECT R_POSITION, WORK_ASSIGNMNT, EMPLOYEE FROM #W) W
ON EP.R_POSITION = W.R_POSITION
AND EP.EMPLOYEE = W.EMPLOYEE
AND EP.WORK_ASSIGNMNT = W.WORK_ASSIGNMNT
),
CTE --Recurse dataset to pass the start date to the end rows of each position/assignment
AS
(
--Anchor query, get start rows (HAS_LAG = 0) and start date (S_DATE)
SELECT *
, EFFECT_DATE AS S_DATE
FROM CTE_PRE WHERE HAS_LAG = 0
UNION ALL
--Recursed query, pass start date (S_DATE) to end rows
SELECT CN.*
, CTE.S_DATE FROM CTE_PRE CN
INNER JOIN CTE
ON
CN.EMPLOYEE = CTE.EMPLOYEE
AND CN.R_POSITION = CTE.R_POSITION
AND CN.WORK_ASSIGNMNT = CTE.WORK_ASSIGNMNT
AND CN.EFFECT_DATE = DATEADD(DAY, 1, CTE.END_DATE)
)
--Get final result
SELECT EMPLOYEE, R_POSITION, WORK_ASSIGNMNT
,MAX(EFFECT_DATE) AS EFFECT_DATE
,MAX(END_DATE) AS END_DATE
FROM
(
-- Get EFFECT_DATE and END_DATE that sit on certain position/assignment continuous
SELECT EMPLOYEE, R_POSITION, WORK_ASSIGNMNT,
S_DATE AS EFFECT_DATE --EFFECT_DATE which passed from first row
, MAX(END_DATE) AS END_DATE
FROM CTE
GROUP BY EMPLOYEE, R_POSITION, WORK_ASSIGNMNT, S_DATE
)F
GROUP BY EMPLOYEE, R_POSITION, WORK_ASSIGNMNT
;
DROP TABLE #W;
DROP TABLE #EP;