4

現在、次のようなアクセスログの表があります

LogID  UserID  BuildingID  Date/Time
===========================================
1      1       1           2013-01-01 10:00
2      2       1           2013-01-01 10:00
3      3       1           2013-01-01 10:30
4      3       2           2013-01-01 11:00
5      2       1           2013-01-01 11:00
6      4       1           2013-01-01 11:30
7      5       1           2013-01-01 11:30
8      5       1           2013-01-01 11:31
9      1       3           2013-01-01 12:00
10     1       3           2013-01-01 12:03
11     1       2           2013-01-01 12:05

私がする必要があるのは、次の 2 つの条件に基づいて、重複するユーザー レコードの数をカウントするクエリを作成することです。

  1. X 分を超える時差 - X は、ユーザーが指定したパラメーターになります。
  2. または、ユーザーの個別の建物ごと

たとえば、時差を 5 分に設定した場合、結果は次のようになります。

UserID   AccessCount
====================
1        3            <-- +1 for timediff (ID 1,10) +1 for building (ID 11)
2        2            <-- +1 for timediff (ID 2,5)
3        2            <-- +1 for building (ID 3,4)
4        1
5        1            <-- duplicate ignored because DateDiff < 5min

うまくいけば、それは理にかなっています。

背景を説明すると、これは一部の建物へのスワイプアクセス用であり、分析セキュリティレポートのビジネス要件が低下しました. 基本的には、特定の期間にアクセスの重複をチェックしたいのですが (通常は週末に行われます)、一部のスワイプ ポイントが失敗し、ユーザーが複数回スワイプする必要があるという事実を考慮する必要があります。これが、スワイプエラーが通常、ユーザーが非常に短い時間内に複数回スワイプすることを意味するため、datediff が必要な理由です。

どんな助けでも大歓迎です、事前に感謝します!

4

2 に答える 2

3

行を数えるときと数えないときを考えることで、ロジックを言い換えることができます。同じ建物にあり、同じ建物の前の日時から特定の期間内にある行はカウントされません。

これはあなたが望むものかもしれないと思います:

select userId, count(*)
from (select LogID, UserID, BuildingID, dt,
             lag(dt) over (partition by userid, buildingid) as prevdt
      from t
     ) t
where dt > prevdt + TIMEDIFF or prevdt is NULL

SQL では、日時に追加された定数は日数として解釈されます。したがって、5 分は になります(5.0/60)/24

データに例はありませんが、3 つの行があるとします。

1   1   1   11:30
2   1   2   11:31
3   1   1   11:32

この場合、行 1 は最初の条件でカバーされるため、行 3 はカウントされません。

于 2013-06-01T14:04:17.830 に答える
0

1 つのアプローチを次に示します。

declare @duplicateMinutes int = 5

select UserID, AccessCount = count(1)
from AccessLogs a
where not exists
  (
    select 1
    from AccessLogs d
    where a.LogID < d.LogID -- add this to try and avoid duplicate times cancelling each other
      and a.UserID = d.UserID
      and a.BuildingID = d.BuildingID
      and a.SwipeTime >= dateadd(mi, -@duplicateMinutes, d.SwipeTime)
      and a.SwipeTime <= d.SwipeTime
  )
group by UserID
order by UserID

SQL Fiddle with demo - データに期待される結果を提供します。

于 2013-06-01T14:10:20.033 に答える