I have a list of employees, along with list of cities they’ve worked in. I need to build a matrix (in SQL Server) of start/end dates by city to determine where they were at any given period in time.
The “end date” would be exactly the date before they appeared at a new location.
I’ve included an example of the source table, and what the output table should appear, along with the code that will build a temp table.
Any recommendations on how I can design this query, and what functions to use?
SOURCE:
x
EMP DATE LOCATION
-----------------------------------
Pinal 2020-01-01 Bangalore
Pinal 2020-01-02 Bangalore
Pinal 2020-01-04 Uttar Pradesh
Pinal 2020-01-06 Uttar Pradesh
Pinal 2020-01-20 Mumbai
Pinal 2020-01-22 Bangalore
Desired query output:
EMP DATE_FROM DATE_TO LOCATION
----------------------------------------------
Pinal 2020-01-01 2020-01-03 Bangalore
Pinal 2020-01-04 2020-01-19 Uttar Pradesh
Pinal 2020-01-20 2020-01-21 Mumbai
Pinal 2020-01-22 2099-01-01 Bangalore
CREATE TABLE #EMP
(
EMP VARCHAR(30) NOT NULL ,
DATE_WORKED DATE NOT NULL ,
CITY VARCHAR(30) NOT NULL
);
INSERT INTO #EMP (EMP, DATE_WORKED, CITY)
VALUES
('Pinal','2020-01-01','Bangalore'),
('Pinal','2020-01-02','Bangalore'),
('Pinal','2020-01-04','Uttar Pradesh'),
('Pinal','2020-01-06','Uttar Pradesh'),
('Pinal','2020-01-20','Mumbai'),
('Pinal','2020-01-22','Bangalore')
Advertisement
Answer
This is a classic Gaps-and-Islands.
Here we use a CROSS APPLY B
to get the Date Range, and then CROSS APPLY C
as an ad-hoc tally table
Example
Select Emp
,FromDate = min(D)
,ToDate = max(D)
,City
From (
Select *
,Grp = datediff(day,'1900-01-01',d) - row_number() over (partition by Emp,City Order By D)
From #Emp A
Cross Apply (
Select NextDate = IsNull(min(DateAdd(DAY,-1,Date_Worked)),'2025-01-01')
From #Emp
Where Emp=A.Emp and Date_Worked>A.Date_Worked
) B
Cross Apply (
Select Top (DateDiff(DAY,Date_Worked,NextDate)+1)
D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),Date_Worked)
From master..spt_values n1,master..spt_values n2
) C
--Where EMP ='Victor'
) A
Group By Emp,City,Grp
Order by Emp,FromDate
Returns
Emp FromDate ToDate City
Pinal 2020-01-01 2020-01-03 Bangalore
Pinal 2020-01-04 2020-01-19 Uttar Pradesh
Pinal 2020-01-20 2020-01-21 Mumbai
Pinal 2020-01-22 2025-01-01 Banga
Victor 2020-01-01 2020-01-18 NYC
Victor 2020-01-19 2020-01-24 San Fran
Victor 2020-01-25 2025-01-01 NYC