1、IFNULL的使用
selectnamefromcustomerwherereferee_id != 2orreferee_id is null
/
优化:
selectnamefromcustomerwhereifnull(referee_id,0)!=2
将null转换为0,然后变为不等于2
2、 游戏玩法分析 II

一般常规的解法:
selectplayer_id,device_idfromActivitywhere(player_id ,event_date )in(selectplayer_id,min(event_date ) event_datefromActivitygroup byplayer_id)
我们想着再优化一下
select player_id, device_idfrom Activitygroup by player_idhaving min(event_date)
我们就有可能会写成这种格式,但是这种格式我们并非是player_id中最小的日期。
min()、max() 和group by 一起用的时候 此时会发现获取到的数据不是最大/最小的;问题根源: group by 默认返回每一组的第一条数据(每一组的数据排序都是按默认顺序排序的)
然后我们用窗口函数做一下
selectt.player_id ,t.device_idfrom(select*,row_number() over(partition by player_id order by event_date) as rkfrom Activity) twhere t.rk=1
3、用union all 代替union
我们都知道SQL语句使用union关键字后,可以 获取排重后的数据。而如果使用Union all关键字,可以获取所有数据,包含重复的数据。
排重的过程需要遍历、排序和比较,它更耗时,更消耗CPU资源,所以如果能用union all的时候尽量不用Union。
4、小表驱动大表
小表驱动大表,也就是说小表的数据集驱动大表的数据集。
in适用于左边大表,右边小表。
exists适用于左边小表,右边大表。
select * from orderwhere user_id in(select id from user where status=1);
select * from orderwhere 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_datefromorderwhere user_id=123order by create_date asc;
正例
select id, create_datefromorderwhere user_id=123order by create_date asc limit 1;
