1

リンクがクリックされるたびに SQL Server 2008 データベースにクライアント メトリックを記録するサイトがあります。1 日の合計クリック数を取得するためのクエリは既に作成していますが、ユーザーが特定の時間内 (つまり 5 秒以内) にクリックした回数を調べたいと考えています。

ここでの考え方は、コンテンツをスクレイピングしようとしている着信 IP アドレスをロックアウトすることです。5 秒以内に 5 回を超える「クリック」が検出された場合、または特定の IP アドレスからの 1 日のクリック数が一定の値を超えた場合、これはスクレイピングの試みであると見なされます。

次のいくつかのバリエーションを試しました。

-- when a user clicked more than 5 times in 5 seconds
SELECT DATEADD(SECOND, DATEDIFF(SECOND, 0, ClickTimeStamp), 0) as ClickTimeStamp, COUNT(UserClickID) as [Count]
FROM UserClicks
WHERE DATEDIFF(SECOND, 0, ClickTimeStamp) = 5
GROUP BY IPAddress, ClickTimeStamp

特に、これは次のエラーを返します。

メッセージ 535、レベル 16、状態 0、行 3 datediff 関数でオーバーフローが発生しました。2 つの日付/時刻インスタンスを区切る日付部分の数が多すぎます。精度の低い datepart で datediff を使用してみてください。

繰り返しになりますが、秒の日付部分を使用したいと思います。これは正しい軌道に乗っていると思いますが、完全には取得できません。

助けていただければ幸いです。ありがとう。

- アップデート -

素晴らしい提案と、アプローチが間違っていると考えるのに役立ちました。チェックはクリックごとに行われます。私がすべきことは、特定のタイムスタンプに対して、過去 5 秒間に同じ IP アドレスから 5 回のクリックが記録されているかどうかを確認することです。> GetDate() - 5 秒のクリック数をカウントします。

以下を試しても、正確な数値が得られません。

SELECT COUNT(*)
FROM UserClicks
WHERE ClickTimeStamp >= GetDate() - DATEADD(SECOND, -5, GetDate())
4

3 に答える 3

1

私の構文が良いことを願って、これをテストするオラクルしかありません。そのユーザーに固有の user_id という ID 列があると仮定します (user_click_id ですか? 可能であれば、これらの質問に table create ステートメントを含めると役立ちます)

これに対して自己結合を実行する必要があります。ロジックは userclick を取得し、userId = userId の userclick に参加し、クリックタイムスタンプの差は 0 ~ 5 秒です。次に、サブセレクトから数えます。

select u1.user_id, u1.clicktimestamp, u2.clicktimestamp
from userclicks uc1
left join user_clicks uc2  
    on u2.userk_id = u1.user_id
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) <= 5
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) > 0

この select ステートメントは、user_id/clicktimestamp と、同じユーザーからの clicktimestamp から 0 ~ 5 秒離れているレコードごとに 1 行を提供する必要があります。これで、すべての user_id,u1.clicktimestamp の組み合わせを数えて、5 つ以上のものを強調表示するだけです。上記のクエリを取得してサブセレクトに変換し、そこからカウントを取得します。

select u1.user_id, u1.clicktimestamp, count(1)
from 
(select u1.user_id, u1.clicktimestamp
from userclicks uc1
left join user_clicks uc2  
    on u2.userk_id = u1.user_id
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) <= 5
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) > 0) a
group by u1.user_id, u1.clicktimestamp
having count(1) >= 5

MS マシンで自分の構文を検証できたらいいのにと思います...そこにタイプミスがあるかもしれませんが、ロジックは適切なはずです。

于 2011-12-05T19:24:54.667 に答える
0

ログエントリが現在のアクティビティに対してのみ入力されると仮定すると、つまり、新しい行が挿入されるたびに、記録された時間はその時点のものであり、それ以前の時点のものではありません。期間を設定し、現在行っているように「すべてのデータ」を確認する必要はありません。

次の質問は、どのくらいの頻度でこのチェックを行いますか? 1 秒あたりのクリック数に関心がある場合は、「1 時間に 1 回」から「24 時間に 1 回」の間が妥当と思われます。

次:あなたの間隔を定義します。「5 秒以内の IP アドレスごとのすべてのクリック」には、設定ウィンドウ (00-04、05-09、10-14 など) またはスライディング ウィンドウ (00-04、01-05、02-06 など) の 2 つの方法があります。 ) 5 秒のウィンドウではおそらく無関係ですが、より長い期間 (「1 日あたりのクリック数」) ではより関連性が高くなる可能性があります。

それで、私が取る一般的なアプローチは次のとおりです。

  • 関心のある最も古い時点から開始します (1 時間前、24 時間前)
  • 「バケット」を設定します。これは、タイム ウィンドウを識別できることを意味します (00:00:00 - 00:00:04、00:00:05 - 00:00:09 など)。これは、一時テーブルとして実行できます。
  • すべてのイベントについて、最も早い時点からの経過秒数を計算します
  • バケットごとに、そのバケットにヒットしたイベントの数をカウントし、IP アドレスでグループ化します ( inner join on the temp table on seconds between lowValue and highValue)
  • あなたの閾値(having count(*) > X)を超えているものを特定し、それらを解放します。
于 2011-12-05T18:48:32.357 に答える
0

あなたのUPDATEの答え:問題はの3行目にあります

SELECT COUNT(*)
 FROM UserClicks
 WHERE ClickTimeStamp >= GetDate() - DATEADD(SECOND, -5, GetDate()) 

GetDate() - DATEADD(SECOND, -5, GetDate())「現在の日時を取り、(現在の日時から 5 秒を引いた値) を引く」と言っています。これがどのような価値を生み出すかは完全にはわかりませんが、あなたが望むものにはなりません.

あなたはまだある種の期間を望んでいます。

SELECT count(*)
 from UserClicks
 where IPAddress = @IPAddress
  and ClickTimeStamp between getdate() and dateadd(second, -5, getdate())

そこで getdate() を使用するのは少し不快です。特定の日時値 (秒単位まで正確) がある場合は、おそらくそれを使用する必要があります。

于 2011-12-05T22:48:35.893 に答える