2017-03-15 6 views
1

Ziel ist das Gruppieren transnationaler Informationen zu Benutzeraktionen in Sitzungen durch Timeout zwischen diesen Datensätzen. (Im Beispiel: Derselbe Benutzer Preform 10 Aktionen innerhalb von 1-3 Minuten zwischen jedem -> Sitzung # 1; und 2 Stunden nach weiteren 10 Aktionen wieder mit wenigen Minuten dazwischen -> Sitzung # 2)Gruppieren von Websitzungen

Beispieleingabe:

id user_id trans_datetime 
1  1   2017-03-16 07:12:01 
2  2   2017-03-16 07:12:02 
3  2   2017-03-16 07:12:12 
4  1   2017-03-16 08:57:00 
5  1   2017-03-16 08:58:01 
6  1   2017-03-16 09:01:50 
7  1   2017-03-16 10:14:01 
8  1   2017-03-16 10:18:01 
9  1   2017-03-16 10:35:11 

Erwartete Ausgabe:

id start_id user_id trans_datetime 
1 1  1   2017-03-16 07:12:01 
2 2  2   2017-03-16 07:12:02 
3 2  2   2017-03-16 07:12:12 
4 4  1   2017-03-16 08:57:00 
5 4  1   2017-03-16 08:58:01 
6 4  1   2017-03-16 09:01:50 
7 7  1   2017-03-16 10:14:01 
8 7  1   2017-03-16 10:18:01 
9 7  1   2017-03-16 10:35:11 

Meine ursprüngliche Idee rekursive CTE zu verwenden war:

With rCTE as (
Select id 
    ,id as start_id 
    ,user_id 
    ,tran_datetime 
from transactions 
where first_transaction_flg = 1 

Union all 

Select child.id 
    ,parent.id as start_id 
    ,child.user_id 
    ,child.tran_datetime 
from transactions child 
Inner Join rCTE parent 
on child.user_id = parent.user_id 
    and child.tran_datetime > parent.datetime 
    and datediff(minute, child.tran_datetime, parent.tran_datetime) < 20 
) 
Select * from rCTE 

Aber es scheint nicht wie beabsichtigt zu funktionieren, und ich kann nicht genau sagen warum.

+2

bitte erklären Sie mit einigen Beispieldaten, addieren Sie erwartetes Ergebnis in Form von Text – TheGameiswar

+0

W Mit welcher Version arbeitest du? –

+0

@ZoharPeled 2014 – JagdCrab

Antwort

1

mit einem common table expression mit einer Unterabfrage zu überprüfen, ob es eine gültige frühere Tätigkeit für jeden trans_datetime ist, und ein outer apply():

;with ses as (
    select 
     t.* 
    , prevTime = (
     select max(i.trans_datetime) 
     from t as i 
     where i.user_id = t.user_id 
      and i.trans_datetime < t.trans_datetime 
      and i.trans_datetime >= dateadd(hour,-1,t.trans_datetime) 
     ) 
    from t 
) 
select 
    id 
    , start_id = case 
     when prevTime is null 
     then id 
     else x.start_id 
     end 
    , user_id 
    , trans_datetime 
from ses 
outer apply (
    select top 1 
    start_id = id 
    from ses i 
    where i.user_id = ses.user_id 
    and i.trans_datetime < ses.trans_datetime 
    and i.prevTime is null 
    order by trans_datetime desc 
    ) x 

rextester Demo: http://rextester.com/CGJSX81463

kehrt:

+----+----------+---------+---------------------+ 
| id | start_id | user_id | trans_datetime | 
+----+----------+---------+---------------------+ 
| 1 |  1 |  1 | 2017-03-16 07:12:01 | 
| 2 |  2 |  2 | 2017-03-16 07:12:02 | 
| 3 |  2 |  2 | 2017-03-16 07:12:12 | 
| 4 |  4 |  1 | 2017-03-16 08:57:00 | 
| 5 |  4 |  1 | 2017-03-16 08:58:01 | 
| 6 |  4 |  1 | 2017-03-16 09:01:50 | 
| 7 |  7 |  1 | 2017-03-16 10:14:01 | 
| 8 |  7 |  1 | 2017-03-16 10:18:01 | 
| 9 |  7 |  1 | 2017-03-16 10:35:11 | 
+----+----------+---------+---------------------+