Mysql按条件计数的几种方法

最近在给喜乐喜乐网的后台添加一系列的统计功能,遇到不少须要按条件计数的状况。尝试了几种方法,下面简要记录,供你们参考。 问题描述 为使讨论简单易懂,我将问题稍做简化,去掉诸多的背景。 从前有一个皇帝,他有50个妃子,这些妃子很没有天理的给他生了100,000个儿子,因而,皇帝很苦恼,海量的儿子很难管理,并且,他想知道每一个妃子给他生了多少个儿子,从而论功行赏,这很难办。因而,皇帝请了一个程序员帮他编了一个程序,用数据库来存储全部的儿子的信息,这样就能够用程序来统计和管理啦。 数据库的结构以下: id 皇子的惟一编号 mother 皇子母亲的惟一编号 皇帝把妃子分红了两个等级,天宫娘娘(编号小于25)和地宫娘娘(编号大于等于25),他想知道天宫娘娘们和地宫娘娘们的生育能力孰强孰弱。因而,程序员开始写SQL Query了。 方法1:使用GROUP BY SQL Query SELECT COUNT(*) FROM `prince` GROUP BY `mother` > 24; 执行结果 count(*) 50029 49971 在100,000行数据上的运行时间:0.0335 秒 分析 这种GROUP BY方法的最大问题在于:没法区分所获得的结果。这两个数字哪个是天宫娘娘们所生的皇子数,哪个是地宫娘娘们所生的皇子数呢?不知道。因此,尽管它统计出了总数,可是没有什么意义。 所以,为了区分统计结果,必需要把条件 mother > 24 也做为一个字段在结果集中做为一个字段体现出来,修改后的sql以下: SELECT COUNT(*) AS `number`, `mother` > 24 AS `type` FROM `prince` GROUP BY `mother` > 24; 执行结果 number  type 50029   0 49971   1 条件表达式做为字段时,该字段的值就是该条件表达式的值,所以,对应咱们的例子,type = 1 也就是表示 mother > 24 的值为1,所以,第二行中的数字表明地宫娘娘们所生的皇子数。 通过修改后,咱们看出,天宫娘娘们略胜一筹。 优缺点 缺点是显而易见的,因为使用了条件表达式做为分组依据,它只能作二元的划分,对于要分红多类进行统计的状况不可以胜任。好比要分别统计1~10号、11~24号,25号~50号妃子的产子数,就没法实现了。 另外,因为使用了GROUP BY,所以涉及到排序,执行时间上要更长。 我暂时没有发现这种方法的优势。 方法2:使用嵌套的SELECT 使用嵌套的SELECT也能够达到目的,在每一个SELECT子句中统计一个条件下的数据,而后用一个主SELECT把这些统计数据整合起来。 SQL Query SELECT      ( SELECT COUNT( * ) FROM `prince` WHERE `mother` >24 ) AS `digong`,     ( SELECT COUNT( * ) FROM `prince` WHERE `mother` <=24 ) AS `tiangong` 执行结果 digong  tiangong 49971   50029 在100,000行数据上的运行时间:0.0216 秒 分析 这种嵌套SELECT的方法很是直观,就是分别统计各个条件下的数值,最后进行汇总,通俗易懂,跟天然语言没啥区别了。 优缺点 优势就是直观,并且速度也比GROUP BY要快。虽然是3条SELECT语句,看起来比GROUP BY的方案多了2条语句,可是它不涉及到排序,这就节省了不少时间。 缺点可能就是语句稍多,对语句数量有洁癖的同窗可能会比较不舒服。 方法3:使用CASE WHEN CASE WHEN语句的功能很强大,能够定义灵活的查询条件,很适合进行分类统计。 SQL Query SELECT      COUNT( CASE WHEN `mother` >24 THEN 1 ELSE NULL END ) AS `digong`,     COUNT( CASE WHEN `mother` <=24 THEN 1 ELSE NULL END ) AS `tiangong` FROM prince 执行结果 digong  tiangong 49971   50029 在100,000行数据上的运行时间:0.02365825 秒 分析 此方法的关键在于 COUNT( CASE WHEN `mother` >24 THEN 1 ELSE NULL END ) 这里的COUNT和CASE WHEN联合使用,作到了分类计数。先使用CASE WHEN,当知足条件时,将字段值设置为 1, 不知足条件时,将字段值设置为NULL,接着COUNT函数仅对非NULL字段进行计数,因而,问题解决。 优缺点 优势嘛,此方法也不涉及到排序,所以运行时间上与方法2至关,SELECT语句减小到了 1 条。 缺点就是语句比较长,对语句长度有洁癖的同窗可能会比较不舒服。 总结 对于肯定分类的按条件计数,能够尽可能不用GROUP BY,从而避免排序动做,加速Query的执行。 若是须要根据某个字段的值进行分类,而该字段的值是可变的,好比皇帝要统计每个妃子的产子数,而他可能不停的再娶不少妃子,这种状况下,使用方法2和方法3就不太灵光了,仍是使用一个GROUP BY来得简单便捷。
相关文章
相关标签/搜索