MySql之优化查询语句

3 篇文章 0 订阅
2 篇文章 0 订阅

 一,减少重复查询   

SELECT t.province AS '省份',t.city as '城市',(select count(DISTINCT accountId) from try_apply_info where accountId = t.accountId) AS '人数'
  FROM try_apply_info t,try_activity a,try_apply ap 
 WHERE a.id = ap.activityId 
   AND ap.id = t.id 
   AND a.startTime >= 20160101 
   AND a.startTime < 20170101 
   AND a.reportTime >= 20160101 
   AND a.reportTime < 20170101 
   AND t.province IS NOT NULL AND t.province <> 'null' 
GROUP BY t.province,t.city
以上的sql需要查询几分钟甚至十几分钟才会出来,然而只需要很小的改动就能极大的提高查询效率,高手一眼就能看出来,
(select count(DISTINCT accountId) from try_apply_info where accountId = t.accountId) AS '人数'
这一句又查询了自身一次,完全没必要,只需改成以下,0.003s就能出结果了,毫秒杀有木有!!!

 count(DISTINCT t.accountId) AS '人数'
二,多用聚合求法

select c.accountId as '用户ID',a.accountName as '用户名',(select count(*) from cs_green_card where status = -1 and accountId = c.accountId) 
as '已使用张数',(select count(*) from cs_green_card 
where status = -2 and accountId = c.accountId) as '已过期张数' from cs_green_card c,cs_account a 
where c.accountId = a.accountId and c.startDate >= 20160101 and c.startDate < 20170401 GROUP BY c.accountId ORDER BY c.createAt desc

查询时间是0.572s,其实也不长,但我们有更好的做法

(select count(*) from cs_green_card where status = -1 and accountId = c.accountId) as '已使用张数'
这里其实也是减少查询,但因为有status = -1这个条件,我们需要用到聚合求法,将满足该条件的数据进行统计,时间缩短为0.02s

(SUM(CASE WHEN c.status = -1 THEN 1 ELSE 0 END) '已使用张数'

三 ,多用LEFT JOIN 联表查询

select a.id as '活动ID',a.title as '标题',a.startTime as '活动开始时间',a.applyTime as '申请截止时间',a.reportTime as '活动结束时间',
(select total from cs_counter where id = a.viewCounterId) as '试用人气',
a.applyNum as '申请人总数',(select COUNT(id) from try_apply_anonymous where activityId = a.id) as '匿名申请数',
(select count(b.id) from try_apply b where b.source = 0 and b.activityId = a.id) as 'PC申请人数',
(select count(b.id) from try_apply b where b.source = 2 and b.activityId = a.id) as 'WAP申请人数',
(select count(b.id) from try_apply b where b.source = 1 and b.activityId = a.id) as 'APP申请人数',
a.amount as '份数',a.specs as '规格',a.price as '价格',
TRUNCATE((select count(id) from try_report where activityId = a.id and `status` > 0)/(select count(id) from try_report where activityId= a.id),2) 
as '报告回收率'
from try_activity a
where a.enable = 1 and a.startTime >= 20160101 and a.startTime < 20160201 GROUP BY a.id; 
根据第一和第二,以上的sql还有很大的改进空间,但这里的重点是left join的用法,下面进行全面升级

SELECT a.id AS '活动ID',a.title AS '标题',a.startTime AS '活动开始时间',a.applyTime AS '申请截止时间',a.reportTime AS '活动结束时间',
       cc.total AS '试用人气',a.applyNum AS '申请人总数',COUNT(taa.id) AS '匿名申请数',
       tx.pc_cnt 'PC申请人数',tx.wap_cnt 'WAP申请人数',tx.app_cnt 'APP申请人数',
       a.amount AS '份数',a.specs AS '规格',a.price AS '价格' ,
       TRUNCATE(SUM(CASE WHEN tr.status > 0 THEN 1 ELSE 0 END)/COUNT(tr.id),2) AS '报告回收率'
   FROM try_activity a 
     LEFT JOIN cs_counter cc ON cc.id = a.viewCounterId
     LEFT JOIN try_apply_anonymous taa ON taa.`activityId` = a.id
     JOIN (SELECT a.id,SUM(CASE WHEN cc.source = 0 THEN 1 ELSE 0 END) pc_cnt,SUM(CASE WHEN cc.source = 2 THEN 1 ELSE 0 END) wap_cnt,
     SUM(CASE WHEN cc.source = 1 THEN 1 ELSE 0 END) app_cnt
         FROM try_activity a  LEFT JOIN try_apply cc ON cc.activityId = a.id GROUP BY id) tx ON tx.id = a.id
     LEFT JOIN try_report tr ON tr.activityId = a.id
WHERE a.enable = 1 AND a.startTime >= 20161201 AND a.startTime < 20170101
   GROUP BY a.id
注意:话说第1种的写法更快,时间是5s左右,但第2种需要10s左右,第1种速度更快的原因在于采用了单表查询,第2种多虽然使用left join 联表查询,但多表查询降低了速度

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值