首页 » 网站建设 » phpcasewhen查询技巧_SQL优化用casewhen优化统计查询

phpcasewhen查询技巧_SQL优化用casewhen优化统计查询

访客 2024-11-16 0

扫一扫用手机浏览

文章目录 [+]

这里为了简洁明了的阐述问题和解决的方法,我简化一下需求模型。

现在数据库有一张订单表(经由简化的中间表),表构造如下:

phpcasewhen查询技巧_SQL优化用casewhen优化统计查询

CREATE TABLE `statistic_order` ( `oid` bigint(20) NOT NULL, `o_source` varchar(25) DEFAULT NULL COMMENT '来源编号', `o_actno` varchar(30) DEFAULT NULL COMMENT '活动编号', `o_actname` varchar(100) DEFAULT NULL COMMENT '参与活动名称', `o_n_channel` int(2) DEFAULT NULL COMMENT '商城平台', `o_clue` varchar(25) DEFAULT NULL COMMENT '线索分类', `o_star_level` varchar(25) DEFAULT NULL COMMENT '订单星级', `o_saledep` varchar(30) DEFAULT NULL COMMENT '营销部', `o_style` varchar(30) DEFAULT NULL COMMENT '车型', `o_status` int(2) DEFAULT NULL COMMENT '订单状态', `syctime_day` varchar(15) DEFAULT NULL COMMENT '按天格式化日期', PRIMARY KEY (`oid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8

项目需求是这样的:

phpcasewhen查询技巧_SQL优化用casewhen优化统计查询
(图片来自网络侵删)

统计某段韶光范围内每天的来源编号数量,个中来源编号对应数据表中的o_source字段,字段值可能为CDE,SDE,PDE,CSE,SSE。

一开始写了这样一段SQL:

select S.syctime_day, (select count() from statistic_order SS where SS.syctime_day = S.syctime_day and SS.o_source = 'CDE') as 'CDE', (select count() from statistic_order SS where SS.syctime_day = S.syctime_day and SS.o_source = 'CDE') as 'SDE', (select count() from statistic_order SS where SS.syctime_day = S.syctime_day and SS.o_source = 'CDE') as 'PDE', (select count() from statistic_order SS where SS.syctime_day = S.syctime_day and SS.o_source = 'CDE') as 'CSE', (select count() from statistic_order SS where SS.syctime_day = S.syctime_day and SS.o_source = 'CDE') as 'SSE' from statistic_order S where S.syctime_day > '2016-05-01' and S.syctime_day < '2016-08-01' GROUP BY S.syctime_day order by S.syctime_day asc;

这种写法采取了子查询的办法,在没有加索引的情形下,55万条数据实行这句SQL,在workbench下等待了将近十分钟,末了报了一个连接中断,通过explain阐明器可以看到SQL的实行操持如下:

每一个查询都进行了全表扫描,五个子查询DEPENDENT SUBQUERY解释依赖于外部查询,这种查询机制是前辈行外部查询,查询出group by后的日期结果,然后子查询分别查询对应的日期中CDE,SDE等的数量,其效率可想而知。

在o_source和syctime_day上加上索引之后,效率提高了很多,大概五秒钟就查询出了却果:

查看实行操持创造扫描的行数减少了很多,不再进行全表扫描了:

这当然还不足快,如果当数据量达到百万级别的话,查询速率肯定是不能容忍的。
一贯在想有没有一种办法,能否直接遍历一次就查询出所有的结果,类似于遍历java中的list凑集,碰着某个条件就计数一次,这样进行一次全表扫描就可以查询出结果集,结果索引,效率该当会很高。

利用sum聚合函数,加上case...when...then...这种“陌生”的用法,有效的办理了这个问题。

详细SQL如下:

select S.syctime_day, sum(case when S.o_source = 'CDE' then 1 else 0 end) as 'CDE', sum(case when S.o_source = 'SDE' then 1 else 0 end) as 'SDE', sum(case when S.o_source = 'PDE' then 1 else 0 end) as 'PDE', sum(case when S.o_source = 'CSE' then 1 else 0 end) as 'CSE', sum(case when S.o_source = 'SSE' then 1 else 0 end) as 'SSE' from statistic_order S where S.syctime_day > '2015-05-01' and S.syctime_day < '2016-08-01' GROUP BY S.syctime_day order by S.syctime_day asc;

关于MySQL中 case...when...then 的用法就不做过多的阐明了,这条SQL很随意马虎理解,先对一条一条记录进行遍历,group by对日期进行了分类,sum聚合函数对某个日期的值进行求和,重点就在于case...when...then对sum的求和奥妙的加入了条件,当o_source = 'CDE'的时候,计数为1,否则为0;当o_source='SDE'的时候......

这条语句的实行只花了一秒多,对付五十多万的数据进行这样一个维度的统计还是比较空想的。

通过实行操持创造,虽然扫描的行数变多了,但是只进行了一次全表扫描,而且是SIMPLE大略查询,以是实行效率自然就高了:

针对这个问题,如果大家有更好的方案或思路,欢迎留言。

作者:赵客缦胡缨v吴钩霜雪明

链接:https://www.jianshu.com/p/996ba4dced04

来源:简书

简书著作权归作者所有,任何形式的转载都请联系作者得到授权并注明出处。

标签:

相关文章

微信第三方登录便捷与安全的完美融合

社交平台已成为人们日常生活中不可或缺的一部分。微信作为我国最受欢迎的社交软件之一,拥有庞大的用户群体。为了方便用户在不同平台间切换...

网站建设 2025-02-18 阅读1 评论0

广东高速代码表解码高速公路管理智慧

高速公路作为国家交通动脉,连接着城市与城市,承载着巨大的物流和人流。广东作为我国经济大省,高速公路网络密布,交通流量巨大。为了更好...

网站建设 2025-02-18 阅读0 评论0