从SQL获取300秒之间具有相同IP地址的用户

时间:2019-03-14 05:27:58

标签: sql sql-server tsql

我有这样的数据

IP Address    | UserName | DateTime            |
198.168.1.101 | User 1   | 2019-01-01 9:00:00  |
198.168.1.101 | User 2   | 2019-01-01 9:00:05  |
198.168.1.101 | User 3   | 2019-01-01 9:00:10  |
198.168.1.101 | User 4   | 2019-01-01 9:00:15  |
198.168.1.101 | User 5   | 2019-01-01 10:00:00 |

根据该记录,用户1至4 的登录时间不到300秒。因此,我需要捕获这些数据并通知系统管理员。

我不知道如何在SQL上查询。条件是

  1. 相同的IP地址
  2. 在300秒内

使用此脚本,我将获得所有该用户

SELECT UA.*
FROM UserAccess UA join
     (SELECT IPAddress
      FROM UserAccess
      GROUP BY IPAddress
      HAVING COUNT(*) > 1
     ) GUA
     on UA.IPAddress = GUA.IPAddress;

我怎么做到的?

5 个答案:

答案 0 :(得分:0)

使用自我加入

DEMO

select distinct A.* FROM t1 a join t1 b 
on a.ipaddress=b.ipaddress and b.datetimeval>a.datetimeval

输出:

ipaddress       username    datetimeval
198.168.1.101   User 1     01/01/2019 09:00:00
198.168.1.101   User 2     01/01/2019 09:00:05
198.168.1.101   User 3     01/01/2019 09:00:10
198.168.1.101   User 4     01/01/2019 09:00:15

答案 1 :(得分:0)

您可以尝试一下。

DECLARE @UserAccess TABLE (IPAddress VARCHAR(16), UserName VARCHAR(20), [DateTime] DATETIME)
INSERT INTO @UserAccess VALUES
('198.168.1.101', 'User 1', '2019-01-01 9:00:00'),
('198.168.1.101', 'User 2', '2019-01-01 9:00:05'),
('198.168.1.101', 'User 3', '2019-01-01 9:00:10'),
('198.168.1.101', 'User 4', '2019-01-01 9:00:15'),
('198.168.1.101', 'User 5', '2019-01-01 10:00:00')

SELECT IPAddress, UserName, [DateTime] FROM @UserAccess U1
    CROSS APPLY (SELECT COUNT(*) CNT FROM @UserAccess U2 WHERE 
                    U1.IPAddress = U2.IPAddress 
                    AND  ( U2.[DateTime] BETWEEN DATEADD(SECOND,-300, U1.[DateTime]) 
                            AND DATEADD(SECOND, 300, U1.[DateTime])) ) X
WHERE X.CNT > 1

结果

IPAddress        UserName             DateTime
---------------- -------------------- -----------------------
198.168.1.101    User 1               2019-01-01 09:00:00.000
198.168.1.101    User 2               2019-01-01 09:00:05.000
198.168.1.101    User 3               2019-01-01 09:00:10.000
198.168.1.101    User 4               2019-01-01 09:00:15.000

答案 2 :(得分:0)

假设您的表包含列,

IP地址|用户名|日期时间|

并且您需要在300秒之内所有用户,

DECLARE @min_time DATETIME
SELECT @min_time = MIN([DateTime]) FROM UserAccess

SELECT * FROM UserAccess WHERE DATEDIFF(s, @min_time, [DateTime]) <300

答案 3 :(得分:0)

您可以使用窗口功能。 LAG函数可让您访问上一个行中的一列;您可以使用它来查找以前的日期时间和时差。

WITH cte AS (
    SELECT ipaddress
         , username
         , datetime
         , LAG(datetime) OVER (PARTITION BY ipaddress ORDER BY datetime) AS prevdatetime
         , LEAD(datetime) OVER (PARTITION BY ipaddress ORDER BY datetime) AS nextdatetime
    FROM t
)
SELECT *
FROM cte
WHERE DATEDIFF(second, prevdatetime, datetime) <= 300
   OR DATEDIFF(second, datetime, nextdatetime) <= 300

Demo on db<>fiddle

答案 4 :(得分:0)

EXISTS可能具有良好的性能,并具有正确的索引:

select t.*
from t
where exists (select 1
              from t2
              where t2.ipaddress = t.ipaddress and
                    t2.datetime >= dateadd(second, -300, t1.datetime) and
                    t2.datetime < dateadd(second, 300, t1.datetime)
                    t2.username <> t.username
             );

我猜您希望用户名不同。

您想要的索引位于(ipaddress, datetime, username)上。