SQL Server: row_number divided by timeout

I have a table with a series of values ​​(IP varchar (15), DateTime datetime2). Each line corresponds to an HTTP request made by the user. I want to assign session numbers for these lines. Different IP addresses have different session numbers. A new session number must be assigned for the same IP address if the last request is older than 30 minutes . Here is an example output:

IP,      DateTime,         SessionNumber, RequestNumber
1.1.1.1, 2012-01-01 00:01, 1,             1
1.1.1.1, 2012-01-01 00:02, 1,             2
1.1.1.1, 2012-01-01 00:03, 1,             3
1.1.1.2, 2012-01-01 00:04, 2,             1 --different IP => new session number
1.1.1.2, 2012-01-01 00:05, 2,             2
1.1.1.2, 2012-01-01 00:40, 3,             1 --same IP, but last request 35min ago (> 30min)

Columns 1 and 2 are inputs, 3 and 4 are the desired outputs. The table shows two users.

Since the base table is really big , how can this be effectively solved ? I would prefer a small number of passes over the data (one or two).

+5
2

.

;WITH CTE1 AS
(
SELECT *,
IIF(DATEDIFF(MINUTE,
       LAG(DateTime) OVER (PARTITION BY IP ORDER BY DateTime),
       DateTime) < 30,0,1) AS SessionFlag
FROM Sessions
), CTE2 AS
(
SELECT *,
       SUM(SessionFlag) OVER (PARTITION BY IP 
                                  ORDER BY DateTime) AS IPSessionNumber
FROM CTE1
)
SELECT IP,
       DateTime,
       DENSE_RANK() OVER (ORDER BY IP, IPSessionNumber) AS SessionNumber,
       ROW_NUMBER() OVER (PARTITION BY IP, IPSessionNumber 
                              ORDER BY DateTime) AS RequestNumber
FROM CTE2

( IP, DateTime, IP, IPSessionNumber), , SessionNumber , ip-/30- .

SessionNumber . .

;WITH CTE1 AS
(
SELECT *,
IIF(DATEDIFF(MINUTE,
       LAG(DateTime) OVER (PARTITION BY IP ORDER BY DateTime),
       DateTime) < 30,0,1) AS SessionFlag
FROM Sessions
), CTE2 AS(
SELECT *,
       SUM(SessionFlag) OVER (ORDER BY DateTime) AS GlobalSessionNo
FROM CTE1
), CTE3 AS(
SELECT *,
       MAX(CASE WHEN SessionFlag = 1 THEN GlobalSessionNo END) 
               OVER (PARTITION BY IP ORDER BY DateTime) AS SessionNumber
FROM CTE2)
SELECT IP,
       DateTime,
       SessionNumber,
       ROW_NUMBER() OVER (PARTITION BY SessionNumber 
                              ORDER BY DateTime) AS RequestNumber
FROM CTE3

4.

+8

, row_number , CTE. , ( ).

CREATE TABLE #T
(
  IP varchar(15),
  DateTime datetime,
  ID int,
  primary key (IP, ID)
)

insert into #T(IP, DateTime, ID)
select IP, DateTime, row_number() over(partition by IP order by DateTime) 
from #sessionRequests

;with C as
(
  select IP,
         ID,
         DateTime,
         1 as Session
  from #T
  where ID = 1
  union all 
  select T.IP,
         T.ID,
         T.DateTime,
         C.Session + case when datediff(minute, C.DateTime, T.DateTime) >= 30 then 1 else 0 end
  from #T as T
    inner join C 
      on T.IP = C.IP and
         T.ID = C.ID + 1
)
SELECT IP,
       DateTime,
       dense_rank() over(order by IP, Session) as SessionNumber,
       row_number() over(partition by IP, Session order by DateTime) as RequestNumber
from C
order by IP, DateTime, SessionNumber, RequestNumber
option (maxrecursion 0)
+2

All Articles