当前位置: 代码迷 >> Sql Server >> 帮忙看看小弟我这个sql如何变得更高效
  详细解决方案

帮忙看看小弟我这个sql如何变得更高效

热度:58   发布时间:2016-04-24 09:55:06.0
帮忙看看我这个sql怎么变得更高效啊
select A.name,A.device_mark,ifnull(CA.Acount,0) as Acount,ifnull(CB.Bcount,0) as Bcount,ifnull(CC.Ccount,0) as Ccount,ifnull(CD.Dcount,0) as Dcount,ifnull(CE.Ecount,0) as Ecount  
 from wx_car_info A left join 
(SELECT device_mark,count(*) as Acount FROM `wx_page` where DATE(`time`)=CURDATE() group by device_mark) CA 
on A.device_mark = CA.device_mark 
left join 
(SELECT device_mark,count(*) as Bcount FROM `wx_page` where DATE(`time`)=date_sub(CURDATE(),interval 1 day) group by device_mark) CB 
on A.device_mark = CB.device_mark 
left join 
(SELECT device_mark,count(*) as Ccount FROM `wx_page` where DATE_FORMAT(`time`,'%V')=DATE_FORMAT(CURDATE(),'%V') group by device_mark) CC 
on A.device_mark = CC.device_mark 
left join 
(SELECT device_mark,count(*) as Dcount FROM `wx_page` where DATE_FORMAT(`time`,'%Y%m')= DATE_FORMAT(CURDATE(),'%Y%m') group by device_mark) CD 
on A.device_mark = CD.device_mark 
left join 
(SELECT device_mark,count(*) as Ecount FROM `wx_page` group by device_mark) CE 
on A.device_mark = CE.device_mark where A.device_state = 1 ;


以上sql要得到的结果大致就是某个设备他的今天,昨天,本周,本月,总计被激活的次数。
返回结果如下,现在随着数据的增多,查询越来越慢,都十多秒了,有办法变快么?


我之前在mysql问过类似问题,没有人关心啊。特地来mssql求指教,具体日期语法可能有区别,但是表关联肯定一样的,求怎么优化。!!!!!
------解决思路----------------------

SELECT device_mark
,IFNULL(COUNT(CASE WHEN DATE(`time`)=CURDATE() THEN 1 END),0) Acount
,IFNULL(COUNT(CASE WHEN DATE(`time`)=date_sub(CURDATE(),interval 1 day) THEN 1 END),0) Bcount
,IFNULL(COUNT(CASE WHEN DATE_FORMAT(`time`,'%V')=DATE_FORMAT(CURDATE(),'%V') THEN 1 END),0) Ccount
,IFNULL(COUNT(CASE WHEN DATE_FORMAT(`time`,'%Y%m')= DATE_FORMAT(CURDATE(),'%Y%m') THEN 1 END),0) Dcount
,IFNULL(COUNT(1),0) Ecount
FROM `wx_page`
GROUP BY device_mark
我这没有MYSQL,你测试一下,大概是这样,这个得到的结果再和wx_car_info左连接
------解决思路----------------------
試一下下面的sql,看數據是否正確

select A.device_mark,
ifnull((select count(*) from wx_car_info CA where CA.device_mark=A.device_mark and DATE(`time`)=CURDATE()),0) as Acount,
ifnull((select count(*) from wx_car_info CB where CB.device_mark=A.device_mark and DATE(`time`)=date_sub(CURDATE(),interval 1 day)),0) as Bcount,  
ifnull((select count(*) from wx_car_info CC where CC.device_mark=A.device_mark and DATE_FORMAT(`time`,'%V')=DATE_FORMAT(CURDATE(),'%V')),0) as Ccount,
ifnull((select count(*) from wx_car_info CD where CD.device_mark=A.device_mark and DATE_FORMAT(`time`,'%Y%m')= DATE_FORMAT(CURDATE(),'%Y%m')),0) as Dcount,
ifnull(count(*),0) as Ecount
from wx_car_info A 
group by device_mark

------解决思路----------------------
目前的情况下只能通过增加中间表,然后做定时任务定时统计中间表的方式提速了
每天定时计算当天被激活次数,月底计算上一个月被激活总次数,年底计算之前被激活的总次数
因为随着时间的推移,前面的数据是不动的,将这些数据统计到中间表中,以备后续统计时使用
1、统计总计:可以取之前年份激活的总次数,加上本年之前各个月的总次数,加上本月之前每天的总次数再加上今天最新被激活的次数
2、计算年度:本年之前各个月的总次数,加上本月之前每天的总次数再加上今天最新被激活的次数
3、计算月度:本月之前每天的总次数再加上今天最新被激活的次数
4、计算本周:本周之前每天的总次数再加上今天最新被激活的次数
5、计算昨天:直接从中间表提取
6、计算当天:从原始表汇总
------解决思路----------------------
查询条件中用到函数转换就很难提高效率了。做个统计表吧。
从 wx_page 中,按 (device_mark,年月日) 分组统计次数,插入统计表,并且把转换好的周、年月也放在记录中。
即统计表的字段为 (device_mark,年月日,年月,周,次数),主键(device_mark,年月日),索引(device_mark,年月),索引(device_mark,周)
统计表的数据永久保留,每天定时更新最后一天的数据;查询前可能也需要更新当天的数据。

然后再从统计表中分别查询 今天,昨天,本周,本月 的次数,就不需要进行函数转换、能够利用到索引,应该可以提高性能了。
  相关解决方案