SQL Backfilling Dates in a Recruiting Funnel - sql

I am working with recruiting funnel data but a lot of the data has missing date stamps for some upstream stages of the funnel (recruiters either skipping or not properly recording candidate movements through the funnel)
I can fetch data with the steps and their order, my objective is to backfill missing entry dates that are upstream from a stage with an entry date (I figured the backfill could be the same date as the date for the next stage that has a date)
Any ideas on how I can do this using SQL?
I created some sample data:
CREATE TABLE stages (
job_id INT,
application_id INT,
stage_name VARCHAR,
stage_order INT,
entered_on DATE,
exited_on DATE
)
;
INSERT INTO stages (job_id, application_id, stage_name, stage_order, entered_on, exited_on)
VALUES (8339915, 24342, 'Application Review', 0, '2015-06-06', '2015-06-22'),
(8339915, 24342, 'Hiring Manager Review', 1, NULL, NULL),
(8339915, 24342, 'Recruiter Phone Screen', 2, '2015-06-07', '2015-06-22'),
(8339915, 24342, 'Phone Interview', 3, NULL, NULL),
(8339915, 24342, 'Phone Interview 2', 4, '2015-06-22', '2015-07-06'),
(8339915, 24342, 'Face to Face', 5, '2015-07-06', '2015-07-24'),
(8339915, 24342, 'Face to Face 2', 6, NULL, NULL),
(8339915, 24342, 'Offer', 7, NULL, NULL),
(8339915, 24342, 'Hired', 1000, NULL, NULL)
;
SELECT *
FROM stages
ORDER BY job_id ASC, application_id ASC, stage_order

This code would help with your requirement but the intermediate join is painful, if you have a low amount of stages this would work just fine. let me know if there is any concern.
Select A.job_id,A.application_id,a.stage_name,a.stage_order,isnull(a.entered_on,ent.entered_on),isnull(a.exited_on,exi.exited_on)
from stages A
left join
(select * from(select *, row_number() over(partition by job_id,application_id,s1 order by s1,s2 desc) rn from(
select job_id,application_id,stage_name,a.stage_order as s1,b.stage_order as s2,isnull(a.entered_on,b.entered_on) as entered_on from stages A
inner join (select distinct stage_order,entered_on from stages where entered_on is not null
)b on A.stage_order>=b.stage_order
where a.entered_on is null) j)k
where K.rn=1)Ent on Ent.job_id=a.job_id and ent.application_id=a.application_id and ent.s1=a.stage_order
left join(
select * from(select *, row_number() over(partition by job_id,application_id,s1 order by s1,s2 desc) rn from(
select job_id,application_id,stage_name,a.stage_order as s1,b.stage_order as s2,isnull(a.exited_on,b.exited_on) as exited_on from stages A
inner join (select distinct stage_order,exited_on from stages where exited_on is not null
)b on A.stage_order>=b.stage_order
where a.exited_on is null) j)k
where K.rn=1)Exi on Exi.job_id=a.job_id and exi.application_id=a.application_id and exi.s1=a.stage_order

Related

Return latest values for each month filling empty values

In SQL Server 2017 I have a table that looks like this https://i.stack.imgur.com/Ry106.png and I would like to get the amount of members at the end of each month, filling out the blank months with the data from the previous month.
So having this table
Create table #tempCenters (
OperationId int identity (1,1) primary key,
CenterId int,
members int,
Change_date date,
Address varchar(100), --non relevant
Sales float --non relevant
)
with this data
INSERT INTO #tempCenters VALUES
(1, 100, '2020-02-20', 'non relevant column', 135135),
(1, 110, '2020-04-15', 'non relevant column', 231635),
(1, 130, '2020-04-25', 'non relevant column', 3565432),
(1, 180, '2020-09-01', 'non relevant column', 231651),
(2, 200, '2020-01-20', 'non relevant column', 321365),
(2, 106, '2020-03-20', 'non relevant column', 34534),
(2, 135, '2020-06-25', 'non relevant column', 3224),
(2, 154, '2020-06-20', 'non relevant column', 2453453)
I am expecting this result
CenterId, Members, EOM_Date
1, 100, '2020-2-28'
1, 100, '2020-3-30'
1, 130, '2020-4-31'
1, 130, '2020-5-30'
1, 130, '2020-6-31'
1, 130, '2020-7-31'
1, 130, '2020-8-30'
1, 180, '2020-9-31'
2, 200, '2020-1-31'
2, 200, '2020-2-28'
2, 106, '2020-3-31'
2, 106, '2020-4-30'
2, 106, '2020-5-31'
2, 135, '2020-6-30'
And this is what I´ve got so far
SELECT
t.centerId,
EOMONTH(t.Change_date) as endOfMonthDate,
t.members
FROM #tempCenters t
RIGHT JOIN (
SELECT
S.CenterId,
Year(S.Change_date) as dateYear,
Month(S.Change_date) as dateMonth,
Max(s.OperationId) as id
FROM #tempCenters S
GROUP BY CenterId, Year(Change_date), Month(Change_date)
) A
ON A.id = t.OperationId
which returns the values per month, but not fill the blank ones.
First I get start date (min date) and finish date (max date) for each CenterId. Then I generate all end of months from start date to finish date for each CenterId. Finally I join my subuqery (cte) with your table (on cte.CenterId = tc.CenterId AND cte.EOM_Date >= tc.Change_date) and get last (previous or same date) members value for each date (end of month).
WITH cte AS (SELECT CenterId, EOMONTH(MIN(Change_date)) AS EOM_Date, EOMONTH(MAX(Change_date)) AS finish
FROM #tempCenters
GROUP BY CenterId
UNION ALL
SELECT CenterId, EOMONTH(DATEADD(MONTH, 1, EOM_Date)), finish
FROM cte
WHERE EOM_Date < finish)
SELECT DISTINCT cte.CenterId,
FIRST_VALUE(Members) OVER(PARTITION BY cte.CenterId, cte.EOM_Date ORDER BY tc.Change_date DESC) AS Members,
cte.EOM_Date
FROM cte
LEFT JOIN #tempCenters tc ON cte.CenterId = tc.CenterId AND cte.EOM_Date >= tc.Change_date
ORDER BY CenterId, EOM_Date;
I know it looks cumbersome and I'm sure there is a more elegant solution, but still you can use a combination of subqueries with union all and outer apply to get the desired result.
Select t.CenterId, Coalesce(t.members, tt.members), t.Change_date
From (
Select CenterId, Max(members) As members, Change_date
From
(Select t.CenterId, t.members, EOMONTH(t.Change_date) As Change_date
From #tempCenters As t Inner Join
(Select CenterId, Max(Change_date) As Change_date
From #tempCenters
Group by CenterId, Year(Change_date), Month(Change_date)
) As tt On (t.CenterId=tt.CenterId And
t.Change_date=tt.Change_date)
Union All
Select t.CenterId, Null As member, t.Change_date
From (
Select tt.CenterId, EOMONTH(datefromparts(tt.[YEAR], t.[MONTH], '1')) As Change_date,
Min_Change_date, Max_Change_date
From (Select [value] as [Month] From OPENJSON('[1,2,3,4,5,6,7,8,9,10,11,12]')) As t,
(Select CenterId, Year(Change_date) As [YEAR],
Min(Change_date) As Min_Change_date, Max(Change_date) As Max_Change_date
From #tempCenters Group by CenterId, Year(Change_date)) As tt) As t
Where Change_date Between Min_Change_date And Max_Change_date) As t
Group by CenterId, Change_date) As t Outer Apply
(Select members
From #tempCenters
Where CenterId=t.CenterId And
Change_date = (Select Max(Change_date)
From #tempCenters Where CenterId=t.CenterId And Change_date<t.Change_date Group by CenterId)) As tt
Order by t.CenterId, t.Change_date

SQL when sum of supplies count reach to the demands count?

I want to generate a query in SqlServer 2014 from two tables, have no relation with each other.
The first one represents the demands. And the second one represents the supplies for them.
Demands(
[DemandId] [int] NOT NULL,
[ItemCode] [nvarchar](50) NULL,
[TotalCount] [int] NULL,
[Date] [datetime] NULL)
Supplies(
[SupplyId] [int] NOT NULL,
[ItemCode] [nvarchar](50) NULL,
[Count] [int] NULL,
[Date] [datetime] NULL)
For example, we have a demand with (TotalCount = 1000, ItemCode = 1, Date = d1)
and two Supplies in (Date = d2, Count = 300, ItemCode = 1) and (Date = d3, Count = 700, ItemCode = 1)
the demand finished in d3 Date, so I want a query to indicate when supplies have finished the demands.
consider the following data:
the result should be:
Item01 2020-01-07
Item02 2020-01-06
I appreciate any help.
A simple summary could be...
treat a demand as a negative amount of supply
combine the two datasets in to a single time series
use a cumulative sum to see the net availability
Such as...
WITH
NetContribution AS
(
SELECT [ItemCode], [Date], [Count] FROM Supplies
UNION ALL
SELECT [ItemCode], [Date], -[TotalCount] FROM Demands
)
SELECT
[ItemCode],
[Date],
[Count] AS NetAvailabilityChange,
SUM([Count])
OVER (PARTITION BY [ItemCode]
ORDER BY [Date],
[Count] DESC
)
AS NetAvailability
FROM
NetContribution
While the NetAvailability is negative, Supply has not yet met Demand. While it's positive, Supply has exceeded Demand.
EDIT: In response to your question edit...
Just use the above query and add a WHERE clause...
WITH
NetContribution AS
(
SELECT [ItemCode], [Date], [Count] FROM Supplies
UNION ALL
SELECT [ItemCode], [Date], -[TotalCount] FROM Demands
),
NetAvailability AS
(
SELECT
[ItemCode],
[Date],
[Count] AS Delta,
SUM([Count])
OVER (PARTITION BY [ItemCode]
ORDER BY [Date],
[Count] DESC
)
AS Amount
FROM
NetContribution
)
SELECT
*
FROM
NetAvailability
WHERE
Amount >= 0
This is my source data
Demand :
'1', 'A', '1000', '2020-12-01'
'4', 'B', '2000', '2020-12-01'
Supply :
'2', 'A', '700', '2020-12-05'
'3', 'A', '300', '2020-12-08'
'5', 'B', '1000', '2020-12-05'
'6', 'B', '1000','2020-12-08'
Performed the below query :
select a.itemcode, case when totaldemand - totalsupply = 0 then endsupplydate
else null end enddate from </b>
(
select 'demand' type,itemcode,sum(quantity) totaldemand,min(demanddate) as
date from demand b group by type,itemcode ) b
inner join (
select 'supply' type,itemcode,sum(quantity) totalsupply,max(supplydate) as
endsupplydate from supply group by type,itemcode) a
on a.itemcode = b.itemcode;
Output you will be getting :
ItemCode,DemandStart,SupplyEnd,QuantityLeft
'A', '2020-12-08'
'B', '2020-12-08'
In the absence of using SUM() OVER() to generate a cumulative sum, you can use a triangular join (Join the current row on to all preceding rows), but on large data sets is nastily slow...
WITH
NetContribution AS
(
SELECT [ItemCode], [Date], SUM([Count]) AS [Count]
FROM (
SELECT [ItemCode], [Date], [Count] FROM Supplies
UNION ALL
SELECT [ItemCode], [Date], -[TotalCount] FROM Demands
)
combined
GROUP BY [ItemCode], [Date]
),
NetAvailability AS
(
SELECT
a.[ItemCode],
a.[Date],
a.[Count] AS Delta,
SUM(b.[Count]) AS Amount
FROM
NetContribution AS a
INNER JOIN
NetContribution AS b
ON a.[ItemCode] = b.[ItemCode]
AND a.[Date] >= b.[Date]
GROUP BY
a.[ItemCode],
a.[Date],
a.[Count]
)
SELECT
*
FROM
NetAvailability
WHERE
Amount >= 0
https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=48660224fc63bcb2803f5a08b8b1311e

Find date of most recent overdue

I have the following problem: from the table of pays and dues, I need to find the date of the last overdue. Here is the table and data for example:
create table t (
Id int
, [date] date
, Customer varchar(6)
, Deal varchar(6)
, Currency varchar(3)
, [Sum] int
);
insert into t values
(1, '2017-12-12', '1110', '111111', 'USD', 12000)
, (2, '2017-12-25', '1110', '111111', 'USD', 5000)
, (3, '2017-12-13', '1110', '122222', 'USD', 10000)
, (4, '2018-01-13', '1110', '111111', 'USD', -10100)
, (5, '2017-11-20', '2200', '222221', 'USD', 25000)
, (6, '2017-12-20', '2200', '222221', 'USD', 20000)
, (7, '2017-12-31', '2201', '222221', 'USD', -10000)
, (8, '2017-12-29', '1110', '122222', 'USD', -10000)
, (9, '2017-11-28', '2201', '222221', 'USD', -30000);
If the value of "Sum" is positive - it means overdue has begun; if "Sum" is negative - it means someone paid on this Deal.
In the example above on Deal '122222' overdue starts at 2017-12-13 and ends on 2017-12-29, so it shouldn't be in the result.
And for the Deal '222221' the first overdue of 25000 started at 2017-11-20 was completly paid at 2017-11-28, so the last date of current overdue (we are interested in) is 2017-12-31
I've made this selection to sum up all the payments, and stuck here :(
WITH cte AS (
SELECT *,
SUM([Sum]) OVER(PARTITION BY Deal ORDER BY [Date]) AS Debt_balance
FROM t
)
Apparently i need to find (for each Deal) minimum of Dates if there is no 0 or negative Debt_balance and the next date after the last 0 balance otherwise..
Will be gratefull for any tips and ideas on the subject.
Thanks!
UPDATE
My version of solution:
WITH cte AS (
SELECT ROW_NUMBER() OVER (ORDER BY Deal, [Date]) id,
Deal, [Date], [Sum],
SUM([Sum]) OVER(PARTITION BY Deal ORDER BY [Date]) AS Debt_balance
FROM t
)
SELECT a.Deal,
SUM(a.Sum) AS NET_Debt,
isnull(max(b.date), min(a.date)),
datediff(day, isnull(max(b.date), min(a.date)), getdate())
FROM cte as a
LEFT OUTER JOIN cte AS b
ON a.Deal = b.Deal AND a.Debt_balance <= 0 AND b.Id=a.Id+1
GROUP BY a.Deal
HAVING SUM(a.Sum) > 0
I believe you are trying to use running sum and keep track of when it changes to positive, and it can change to positive multiple times and you want the last date at which it became positive. You need LAG() in addition to running sum:
WITH cte1 AS (
-- running balance column
SELECT *
, SUM([Sum]) OVER (PARTITION BY Deal ORDER BY [Date], Id) AS RunningBalance
FROM t
), cte2 AS (
-- overdue begun column - set whenever running balance changes from l.t.e. zero to g.t. zero
SELECT *
, CASE WHEN LAG(RunningBalance, 1, 0) OVER (PARTITION BY Deal ORDER BY [Date], Id) <= 0 AND RunningBalance > 0 THEN 1 END AS OverdueBegun
FROM cte1
)
-- eliminate groups that are paid i.e. sum = 0
SELECT Deal, MAX(CASE WHEN OverdueBegun = 1 THEN [Date] END) AS RecentOverdueDate
FROM cte2
GROUP BY Deal
HAVING SUM([Sum]) <> 0
Demo on db<>fiddle
You can use window functions. These can calculate intermediate values:
Last day when the sum is negative (i.e. last "good" record).
Last sum
Then you can combine these:
select deal, min(date) as last_overdue_start_date
from (select t.*,
first_value(sum) over (partition by deal order by date desc) as last_sum,
max(case when sum < 0 then date end) over (partition by deal order by date) as max_date_neg
from t
) t
where last_sum > 0 and date > max_date_neg
group by deal;
Actually, the value on the last date is not necessary. So this simplifies to:
select deal, min(date) as last_overdue_start_date
from (select t.*,
max(case when sum < 0 then date end) over (partition by deal order by date) as max_date_neg
from t
) t
where date > max_date_neg
group by deal;

Use recursive CTE to handle date logic

At work, one of my assignments is to calculate commission to the sales staff. One rule has been more challenging than the others.
Two sales teams A and B work together each selling different products. Team A can send leads to team B. The same customer might be send multiple times. The first time a customer (ex. lead 1)* is send a commission is paid to the salesperson in team A who created the lead. Now the customer is “locked” for the next 365 days (counting from the date lead 1 was created). Meaning that no one can get additional commission for that customer in that period by sending additional leads (ex. Lead 2 and 3 gets no commission). After the 365 days have expired. A new lead can be created and receive commission (ex. Lead 4). Then the customer is locked again for 365 days counting from the day lead 4 was created. Therefore, lead 5 gets no commission. The tricky part is to reset the date that the 365 days is counted from.
'* Reference to tables #LEADS and #DISERED result.
I have solved the problem in tSQL using a cursor, but I wonder if it was possible to use a recursive CTE instead. I have made several attempts the best one is pasted in below. The problem with my solution is, that I refer to the recursive table more than once. I have tried to fix that problem with nesting a CTE inside a CTE. That’s is not allowed. I have tried using a temporary table inside the CTE that is not allowed either. I tried several times to recode the recursive part of the CTE so that the recursive table is referenced only once, but then I am not able to get the logic to work.
I am using SQL 2008
IF OBJECT_ID('tempdb.dbo.#LEADS', 'U') IS NOT NULL
DROP TABLE #LEADS;
CREATE TABLE #LEADS (LEAD_ID INT, CUSTOMER_ID INT, LEAD_CREATED_DATE DATETIME, SALESPERSON_NAME varchar(20))
INSERT INTO #LEADS
VALUES (1, 1, '2013-09-01', 'Rasmus')
,(2, 1, '2013-11-01', 'Christian')
,(3, 1, '2014-01-01', 'Nadja')
,(4, 1, '2014-12-24', 'Roar')
,(5, 1, '2015-12-01', 'Kristian')
,(6, 2, '2014-01-05', 'Knud')
,(7, 2, '2015-01-02', 'Rasmus')
,(8, 2, '2015-01-08', 'Roar')
,(9, 2, '2016-02-05', 'Kristian')
,(10, 2, '2016-03-05', 'Casper')
SELECT *
FROM #LEADS;
IF OBJECT_ID('tempdb.dbo.#DISERED_RESULT', 'U') IS NOT NULL
DROP TABLE #DISERED_RESULT;
CREATE TABLE #DISERED_RESULT (LEAD_ID INT, DESIRED_COMMISION_RESULT CHAR(3))
INSERT INTO #DISERED_RESULT
VALUES (1, 'YES')
,(2, 'NO')
,(3, 'NO')
,(4, 'YES')
,(5, 'NO')
,(6, 'YES')
,(7, 'NO')
,(8, 'YES')
,(9, 'YES')
,(10, 'NO')
SELECT *
FROM #DISERED_RESULT;
WITH COMMISSION_CALCULATION AS
(
SELECT T1.*
,COMMISSION = 'YES'
,MIN_LEAD_CREATED_DATE AS COMMISSION_DATE
FROM #LEADS AS T1
INNER JOIN (
SELECT A.CUSTOMER_ID
,MIN(A.LEAD_CREATED_DATE) AS MIN_LEAD_CREATED_DATE
FROM #LEADS AS A
GROUP BY A.CUSTOMER_ID
) AS T2 ON T1.CUSTOMER_ID = T2.CUSTOMER_ID AND T1.LEAD_CREATED_DATE = T2.MIN_LEAD_CREATED_DATE
UNION ALL
SELECT T10.LEAD_ID
,T10.CUSTOMER_ID
,T10.LEAD_CREATED_DATE
,T10.SALESPERSON_NAME
,T10.COMMISSION
,T10.COMMISSION_DATE
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY T5.CUSTOMER_ID ORDER BY T5.LEAD_CREATED_DATE ASC) AS RN
,T5.*
,T6.MAX_COMMISSION_DATE
,DATEDIFF(DAY, T6.MAX_COMMISSION_DATE, T5.LEAD_CREATED_DATE) AS ANTAL_DAGE_SIDEN_SIDSTE_COMMISSION
,CASE
WHEN DATEDIFF(DAY, T6.MAX_COMMISSION_DATE, T5.LEAD_CREATED_DATE) > 365 THEN 'YES'
ELSE 'NO'
END AS COMMISSION
,CASE
WHEN DATEDIFF(DAY, T6.MAX_COMMISSION_DATE, T5.LEAD_CREATED_DATE) > 365 THEN T5.LEAD_CREATED_DATE
ELSE NULL
END AS COMMISSION_DATE
FROM #LEADS AS T5
INNER JOIN (SELECT T4.CUSTOMER_ID
,MAX(T4.COMMISSION_DATE) AS MAX_COMMISSION_DATE
FROM COMMISSION_CALCULATION AS T4
GROUP BY T4.CUSTOMER_ID) AS T6 ON T5.CUSTOMER_ID = T6.CUSTOMER_ID
WHERE T5.LEAD_ID NOT IN (SELECT LEAD_ID FROM COMMISSION_CALCULATION)
) AS T10
WHERE RN = 1
)
SELECT *
FROM COMMISSION_CALCULATION;
I have made some assumptions where your description does not fully make sense as written, but the below achieves your desired result:
if object_id('tempdb.dbo.#leads', 'u') is not null
drop table #leads;
create table #leads (lead_id int, customer_id int, lead_created_date datetime, salesperson_name varchar(20))
insert into #leads
values (1, 1, '2013-09-01', 'rasmus')
,(2, 1, '2013-11-01', 'christian')
,(3, 1, '2014-01-01', 'nadja')
,(4, 1, '2014-12-24', 'roar')
,(5, 1, '2015-12-01', 'kristian')
,(6, 2, '2014-01-05', 'knud')
,(7, 2, '2015-01-02', 'rasmus')
,(8, 2, '2015-01-08', 'roar')
,(9, 2, '2016-02-05', 'kristian')
,(10, 2, '2016-03-05', 'casper')
if object_id('tempdb.dbo.#disered_result', 'u') is not null
drop table #disered_result;
create table #disered_result (lead_id int, desired_commision_result char(3))
insert into #disered_result
values (1, 'yes'),(2, 'no'),(3, 'no'),(4, 'yes'),(5, 'no'),(6, 'yes'),(7, 'no'),(8, 'yes'),(9, 'yes'),(10, 'no')
with rownum
as
(
select row_number() over (order by customer_id, lead_created_date) as rn -- This is to ensure an incremantal ordering id
,lead_id
,customer_id
,lead_created_date
,salesperson_name
from #leads
)
,cte
as
(
select rn
,lead_id
,customer_id
,lead_created_date
,salesperson_name
,'yes' as commission_result
,lead_created_date as commission_window_start
from rownum
where rn = 1
union all
select r.rn
,r.lead_id
,r.customer_id
,r.lead_created_date
,r.salesperson_name
,case when r.customer_id <> c.customer_id -- If the customer ID has changed, we are at a new commission window.
then 'yes'
else case when r.lead_created_date > dateadd(d,365,c.commission_window_start) -- This assumes the window is 365 days and not one year (ie. Leap years don't add a day)
then 'yes'
else 'no'
end
end as commission_result
,case when r.customer_id <> c.customer_id
then r.lead_created_date
else case when r.lead_created_date > dateadd(d,365,c.commission_window_start) -- This assumes the window is 365 days and not one year (ie. Leap years don't add a day)
then r.lead_created_date
else c.commission_window_start
end
end as commission_window_start
from rownum r
inner join cte c
on(r.rn = c.rn+1)
)
select lead_id
,commission_result
from cte
order by customer_id
,lead_created_date;

Finding time difference between two times in different rows

Scenario: Database for Biometric device. It inserts
EmpId, EmpName, DepName, RecTime, RecDate
It gets inserted when User Enters office and swipes finger and then 2nd time when he leaves office. RecTime saves Entry time then Exit time.
Problem:
I want to calculate total time a person has worked but finding difference between RecTime in first record being inserted and 2nd record being inserted, in minutes and hours.
I tried DateDiff function, DateSub etc but nothing worked
Not going to solve your problem as there is insufficient data to do so.
The approach pattern I would follow is;
CREATE TABLE #EmpLogging
(
LogID INT,
EmpId INT,
EmpName VARCHAR(50),
DepName VARCHAR(50),
RecTime TIME,
RecDate DATE
)
INSERT INTO #EmpLogging
SELECT 1, 1, 'Fred', 'Legal', '08:00:00', '2013-01-01' UNION ALL
SELECT 2, 2, 'Susan', 'Marketing', '08:03:00', '2013-01-01' UNION ALL
SELECT 3, 1, 'Fred', 'Legal', '17:00:00', '2013-01-01' UNION ALL
SELECT 4, 2, 'Susan', 'Marketing', '17:55:00', '2013-01-01'
;WITH EmpSequence AS
(
SELECT *
,EmpSeq = ROW_NUMBER() OVER (PARTITION BY EmpId ORDER BY RecDate, RecTime)
FROM #EmpLogging
)
,EndTime AS
(
SELECT E1.*
,OutTime = E2.RecTime
,OutDate = E2.RecDate
FROM EmpSequence E1
LEFT
JOIN EmpSequence E2 ON E1.EmpId = E2.EmpId
AND E1.EmpSeq = E2.EmpSeq - 1
)
SELECT *
,MINUTETimeFrame = DATEDIFF(MI, RecTime, OutTime)
FROM EndTime