2017-01-16 10 views
0

Webサイトへのユーザー対話を記録し、[UserId]や[LogDate]などの値を含むログを保存するアクティビティデータベースがあります。Microsoft SQLサーバーは30分ごとに区別されます。

UserId|LogDate 
123 |2017-01-01 11:17:35.190 

私は時間の経過とともに別個のユーザーセッションの数を調べようとしています。これは、個別のユーザカウントすることにより、十分に簡単だろう

:これはその後、分類されたとしてしかし

SELECT COUNT(DISTINCT UserId) FROM ActivityDatabase.dbo.Logs 

は、私は彼らがログに以前のログから30分以上を持っている場合は、複数回の利用者をカウントする必要があります新しいセッションとして。

セッションは、30分の時間枠内にログを持つものとして定義されています。例:ユーザーが13.40で、別のログを作成する場合

  1. ユーザーは13.30でログを作成する場合は、時間をかけて個別のユーザーのための値 セッションは1
  2. だろうことは、カウントはまだのように1でなければなりませんそれは前回のログから30分以内です。
  3. ユーザーが14.20に別のログを作成した場合、前のログの30分後にカウントが2になるはずです。

これはSQLで可能ですか?以前のユーザーログと比較してユーザーのすべてのログを確認する方法が必要です。これらの時間差が30分を超える場合は、一意のセッションとしてカウントされます。

SQLの出力は、期間ではなく数値でなければなりません。

ありがとうございます。

+0

クエリがアプリケーションによって呼び出されている場合、レコードを取得し、日付でソートし、アプリケーションコードを使用してセッションを識別する方が簡単です。 –

答えて

2

セッション化は少しトリッキーです。それを行う方法を教えてください。おそらくこれはあなたの問題を解決します:

select userid, min(log_date) as session_start, 
     dateadd(minute, 30, max(log_date)) as session_end, 
     row_number() over() as session_id 
from (select l.*, 
      sum(case when log_date < dateadd(minute, 30, prev_logdate) 
         then 0 else 1 
       end) over (partition by userid order by logdate 
          ) as grp 
     from (select l.*, 
        lag(logdate) over (partition by userid order by logdate) as prev_logdate 
      from ActivityDatabase.dbo.Logs l 
      ) l 
    ) l 
group by userid, grp; 

あなたはその後、特定の時点でユニークユーザー数、必要な場合:

with s as (
     select userid, min(log_date) as session_start, 
      dateadd(minute, 30, max(log_date) as session_end, 
      row_number() over() as session_id 
     from (select l.*, 
        sum(case when log_date < dateadd(minute, 30, prev_logdate) 
          then 0 else 1 
         end) over (partition by userid order by logdate 
           ) as grp 
      from (select l.*, 
         lag(logdate) over (partition by userid order by logdate) as prev_logdate 
        from ActivityDatabase.dbo.Logs l 
       ) l 
      ) l 
     group by userid, grp 
    ) 
select count(*) 
from s 
where @datetime between session_start and session_end; 

を与えられた時間のためのより強引な選択肢がある:

+0

トップの声明が働いた、ありがとう。私はmax(log_date)の後にカッコを付けて開きカッコのバランスをとり、カッコ内に 'order by userid'を追加しました。再度、感謝します。 –

0

使用しようとしている定義を使いこなすと、SQLを書くのがずっと簡単になります。

「開始ログ」 - セッションの開始を示すログです。我々は他のログを特定したくない。

"開始ログ"はどのように定義しますか? 30分以内に別のログを持たないログです。あなたは、SQL Server 2012以降を使用している場合

SELECT COUNT(*) 
FROM ActivityDatabase.dbo.Logs l1 
WHERE NOT EXISTS (
    SELECT * FROM ActivityDatabase.dbo.Logs l2 
    WHERE l1.UserId = l2.UserId AND 
      l2.LogDate < l1.LogDate AND 
      l2.LogDate >= DATEADD(minute,-30,l1.LogDate) 
    ) 
1

は、私が前の行を見つけるために、ラグ機能を使用すると、あなたは差がより大きく30分

select 
userId, 
LogDate, 
LAG(LogDate, 1,0) OVER (PARTITION BY userId ORDER BY LogDate) AS PreviousLogDate 
from logTbl 
であるかどうかを確認するために、2つの日付時刻を比較することができます

次に、datediffとcase文を追加して、その差がしきい値より大きい新しいログインにフラグを立てることができます。

前の行が見つからない場合、ラグ関数はnullを返します。

関連する問題