需求说明
有一张记录登录行为的表:loginfo(ID,IP,LOGTIME),其中ID是主键,IP记录登录地址,LOGTIME记录登录时间
查询需求:查询在任意10分钟内登陆超过10次的IP
测试数据准备
create table loginfo as
(select 01 ID,'192.168.1.1' IP, to_date('2014-10-01 07:30:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 02 ID,'192.168.1.1' IP, to_date('2014-10-01 07:31:10','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 03 ID,'192.168.1.1' IP, to_date('2014-10-01 07:31:50','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 04 ID,'192.168.1.1' IP, to_date('2014-10-01 07:32:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 05 ID,'192.168.1.1' IP, to_date('2014-10-01 07:33:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 06 ID,'192.168.1.1' IP, to_date('2014-10-01 07:34:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 07 ID,'192.168.1.1' IP, to_date('2014-10-01 07:35:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 08 ID,'192.168.1.1' IP, to_date('2014-10-01 07:35:20','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 09 ID,'192.168.1.1' IP, to_date('2014-10-01 07:35:50','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 10 ID,'192.168.1.1' IP, to_date('2014-10-01 07:36:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 11 ID,'192.168.1.1' IP, to_date('2014-10-01 07:37:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 12 ID,'192.168.1.1' IP, to_date('2014-10-01 07:40:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 13 ID,'192.168.1.1' IP, to_date('2014-10-01 07:40:20','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 14 ID,'192.168.1.1' IP, to_date('2014-10-01 07:41:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 15 ID,'192.168.1.1' IP, to_date('2014-10-01 07:42:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 16 ID,'192.168.1.1' IP, to_date('2014-10-01 07:45:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 17 ID,'192.168.1.1' IP, to_date('2014-10-01 07:46:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 18 ID,'192.168.1.1' IP, to_date('2014-10-01 07:47:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 19 ID,'192.168.1.1' IP, to_date('2014-10-01 07:48:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 20 ID,'192.168.1.2' IP, to_date('2014-10-01 07:30:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 21 ID,'192.168.1.2' IP, to_date('2014-10-01 07:31:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 22 ID,'192.168.1.2' IP, to_date('2014-10-01 07:32:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 23 ID,'192.168.1.2' IP, to_date('2014-10-01 07:35:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 24 ID,'192.168.1.2' IP, to_date('2014-10-01 07:36:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 25 ID,'192.168.1.2' IP, to_date('2014-10-01 07:36:20','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 26 ID,'192.168.1.2' IP, to_date('2014-10-01 07:37:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 27 ID,'192.168.1.2' IP, to_date('2014-10-01 07:38:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 28 ID,'192.168.1.2' IP, to_date('2014-10-01 07:39:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 29 ID,'192.168.1.2' IP, to_date('2014-10-01 07:39:30','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 30 ID,'192.168.1.2' IP, to_date('2014-10-01 07:40:20','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 31 ID,'192.168.1.2' IP, to_date('2014-10-01 07:41:00','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual union all
select 32 ID,'192.168.1.2' IP, to_date('2014-10-01 07:42:20','YYYY-MM-DD HH24:MI:SS') as LOGTIME from dual
);
推导过程
1° 使用自连接,自己连接自己,做笛卡尔积,生成m*m条记录,从select子句中剔除掉不需要的列:
select t1.IP, t1.ID ID1, t2.ID ID2,
t1.LOGTIME time1, t2.LOGTIME time2
from loginfo t1, loginfo t2;
2° 观察生成的笛卡尔积,根据需求,不同的IP之间做比较是没有意义的,因此加入筛选条件 t1.IP=t2.IP
为了更方便看出记录的规律,加入order by语句:
select t1.IP, t1.ID ID1, t2.ID ID2,
t1.LOGTIME time1, t2.LOGTIME time2
from loginfo t1, loginfo t2
where t1.IP=t2.IP
order by t1.ID,t2.ID;
3° 要看出是否是10分钟之内的连续登陆,需要比较两表的LOGTIME关系
要求第二张表的登录时间在第一张表的登录时间的十分钟内
因此加入筛选条件 t1.LOGTIME+1/24/60*10>=t2.LOGTIME:
select t1.IP, t1.ID ID1, t2.ID ID2,
t1.LOGTIME time1, t2.LOGTIME time2
from loginfo t1, loginfo t2
where t1.IP=t2.IP
and t1.LOGTIME+1/24/60*10>=t2.LOGTIME
order by t1.ID,t2.ID;
4° 主键列 ID 唯一标识一次登录行为,那么 ID1>ID2 则表示同一 IP 的后一次登录和前一次登录做比较,无意义
同时 ID1=ID2 则表示同一 IP 的同一次登录做比较,也是没有意义的,因此加入筛选条件 ID1<ID2
select t1.IP, t1.ID ID1, t2.ID ID2,
t1.LOGTIME time1, t2.LOGTIME time2
from loginfo t1, loginfo t2
where t1.IP=t2.IP
and t1.LOGTIME+1/24/60*10>=t2.LOGTIME
and t1.id<t2.id
order by t1.ID,t2.ID;
5° 此时就能看出10分钟内连续登陆超过10次的IP了
同一IP,列 ID1 的某个值如果重复出现超过9次,则该IP满足条件
需要注意理解此处的9的由来,超过10次的连续登录只要大于等于9次就可以了
如:192.168.1.1,ID1=1 出现11次,一直到 ID2=12
就是说该IP的第1次登录时间+10分钟大于等于第12次的登录时间
第1次登录之后的十分钟之内又连续登陆了11次,连续登陆12次
根据IP和ID1分组,求count(*) 10分钟内的连续登陆次数,筛选出大于等于10次的记录:
select t1.IP, t1.ID, count(*)
from loginfo t1, loginfo t2
where t1.IP=t2.IP
and t1.LOGTIME+1/24/60*10>=t2.LOGTIME
and t1.id<t2.id
group by t1.IP, t1.ID
having count(*)>=9
order by t1.IP, t1.ID;
6° 如查询结果所示,ID=1 的登录行为后,10分钟内又登陆了11次,连续登陆12次
依次类推:ID=2 的登录行为后,10分钟内又登陆了12次,连续登陆13次
但是我们不需要显示第几次登录的信息,也不需要显示该次登陆后连续登陆了多少次的信息
最终需要展示的只是IP信息,因此直接对IP滤重即可:
select distinct t1.IP
from loginfo t1, loginfo t2
where t1.IP=t2.IP
and t1.LOGTIME+1/24/60*10>=t2.LOGTIME
and t1.id<t2.id
group by t1.IP, t1.ID
having count(*)>=9;
[TOC]