1、IFNULL的使用
select
name
from
customer
where
referee_id != 2
or
referee_id is null
/
优化:
select
name
from
customer
where
ifnull(referee_id,0)!=2
将null转换为0,然后变为不等于2
2、 游戏玩法分析 II
一般常规的解法:
select
player_id,
device_id
from
Activity
where
(player_id ,event_date )
in
(
select
player_id,
min(event_date ) event_date
from
Activity
group by
player_id
)
我们想着再优化一下
select player_id, device_id
from Activity
group by player_id
having min(event_date)
我们就有可能会写成这种格式,但是这种格式我们并非是player_id中最小的日期。
min()、max() 和group by 一起用的时候 此时会发现获取到的数据不是最大/最小的;问题根源: group by 默认返回每一组的第一条数据(每一组的数据排序都是按默认顺序排序的)
然后我们用窗口函数做一下
select
t.player_id ,
t.device_id
from
(
select
*,
row_number() over(partition by player_id order by event_date) as rk
from Activity
) t
where t.rk=1
3、用union all 代替union
我们都知道SQL语句使用union关键字后,可以 获取排重后的数据。而如果使用Union all关键字,可以获取所有数据,包含重复的数据。
排重的过程需要遍历、排序和比较,它更耗时,更消耗CPU资源,所以如果能用union all的时候尽量不用Union。
4、小表驱动大表
小表驱动大表,也就是说小表的数据集驱动大表的数据集。
in适用于左边大表,右边小表。
exists适用于左边小表,右边大表。
select * from order
where user_id in(select id from user where status=1);
select * from order
where exists(select 1 from user where order.user_id = user.id and status=1);
5、批量操作
如果你有一批数据经过业务处理之后,需要插入数据,该怎么办?反例需要多次请求数据库,才能完成这批数据的插入,而正例只需要远程请求一次数据库,sql性能会得到提升,数据量越多,提升越大
反例
for(Order order : list){
orderMapper.insert(order)
}
insert into order(id,code,user_id)
values(123,'001',100);
正例
orderMapper.insertBatch(list);
insert into order(id,code,user_id)
values(123,'001',100),(124,'001',200);
6、多用limit
有时候,我们需要查询某些数据中的第一条,比如:查询某个用户下的第一个订单,想看看他第一次的首单时间。反例会根据用户id查询订单,返回订单数据,取第一个,而使用Limit 1,只返回该用户下单时间最小的那一条数据即可
反例
select id, create_date
from
order
where user_id=123
order by create_date asc;
正例
select id, create_date
from
order
where user_id=123
order by create_date asc limit 1;