#建测试表drop table if exists t;CREATE TABLE t (id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '自增主键',dept tinyint not null comment '部门id',age tinyint not null comment '年龄',name varchar(30) comment '用户名称',create_time datetime not null comment '注册时间',last_login_time datetime comment '最后登录时间') comment '测试表';INSERT INTO t VALUES(1,1,25,'user_1','2018-01-01 00:00:00','2018-03-01 12:00:00');INSERT INTO t VALUES(2,2,45,'user_2','2018-01-01 00:02:40','2018-01-04 02:37:46');INSERT INTO t VALUES(3,2,26,'user_3','2018-01-01 00:02:09','2018-01-06 07:34:46');INSERT INTO t VALUES(4,2,22,'user_4','2018-01-01 20:05:56','2018-01-01 20:48:21');INSERT INTO t VALUES(5,2,23,'user_5','2018-01-01 00:05:55','2018-01-05 18:19:01');INSERT INTO t VALUES(6,5,46,'user_6','2018-01-01 12:11:58','2018-01-09 23:31:44');INSERT INTO t VALUES(7,5,31,'user_7','2018-01-01 00:11:15','2018-01-11 03:46:36');INSERT INTO t VALUES(8,5,25,'user_8','2018-01-01 00:11:56','2018-01-12 01:16:02');INSERT INTO t VALUES(9,5,49,'user_9','2018-01-01 00:03:09','2018-01-05 21:09:50');INSERT INTO t VALUES(10,6,24,'user_10','2018-01-01 00:14:20','2018-01-03 03:30:44');
表初始化后是长这样子的:

我们先看下开发同学写的sql:
select * from twhere case when dept=2and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'then age<25when dept=5and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'then age>45else 1end;
其执行结果为:

select * from twhere (case when dept=2and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age>=25then 0when dept=5and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age<=45then 0else 1end) = 1;
这样就很好理解了,最重要的是,该语句在Oracle和SQL Server也兼容。
#初始化序列变量set @i=1;#========此处拷贝反复执行15次,生成32万+的测试数据==========insert into t(dept, age, name, create_time, last_login_time)select left(rand()*10,1) as dept, #随机生成1~10的整数FLOOR(20+RAND() *(50 - 20 + 1)) as age, #随机生成20~50的整数concat('user_',@i:=@i+1), #按序列生成不同的namedate_add(create_time,interval +@i*cast(rand()*100 as signed) SECOND), #生成有时间大顺序随机注册时间date_add(date_add(create_time,interval +@i*cast(rand()*100 as signed) SECOND), interval + cast(rand()*1000000 as signed) SECOND) #生成有时间大顺序的随机的最后登录时间from t;#=====================此处结束反复执行=====================#创建索引以供测试create index idx_create_time on t(create_time);
select * from twhere (case when dept=2and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age<25then 1when dept=5and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age>45then 1else 0end) = 1;
执行出来的结果如下:

我们查看执行计划发现也是全表扫描的:

然后我们使用or进行改造:
select * from twhere ( dept=2and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age<25)or( dept=5and create_time>='2018-01-01 00:00:00'and create_time<'2018-01-01 03:00:00'and age>45)
执行出来的结果如下:

执行结果和where条件使用case when一样,再看其执行计划:

文章转载自小灯数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




