Give this a try. I have not actually tested the code because I don't have any test data. If it does not do what you are looking for, can you post some test data that can be copied and pasted to create a test table and data? This is only a select - if it works as expected, it can be easily changed into an update;WITH cte1 AS( SELECT *, ROW_NUMBER() OVER (PARTITION BY [Visitor Id] ORDER BY [Event Time]) AS RN FROM YourTable),cte2 AS( SELECT *, 1 AS session_id, [Event Time] AS StartEventTime FROM cte1 WHERE RN = 1 UNION ALL SELECT c1.*, CASE WHEN DATEDIFF(mm,c2.[Event Time],c1.[Event Time]) > 30 OR DATEDIFF(mm,c2.StartEventTime,c1.[Event Time]) > 12*60 THEN c1.session_id + 1 ELSE c1.session_id END, CASE WHEN DATEDIFF(mm,c2.[Event Time],c1.[Event Time]) > 30 OR DATEDIFF(mm,c2.StartEventTime,c1.[Event Time]) > 12*60 THEN c2.[Event Time] ELSE c1.StartEventTime END FROM cte1 c1 INNER JOIN cte2 c2 ON c1.RN = c2.RN+1)SELECT * FROM cte2;