常见统计分析—按条件统计绝对数量及相对占比

在常见的业务场景中经常会遇到分类统计的问题,如下表所示学生分数,需求:

1.取得不同分数段学生的绝对数量(优良中差数量)

2.取得不同分数段学生的相对情况(优良中差占比)

表名:score

sid cid score

01  01  80

01  02  90

01  03  99

02  01  70

02  02  60

02  03  80

03  01  80

03  02  80

03  03  80

04  01  50

04  02  30

04  03  20

05  01  76

05  02  87

06  01  31

06  03  34

07  02  89

07  03  98

(1)考察点: case when 函数使用

select
    *,
    (
    case
        when score < 60 then 'fail' # 注意此处不需要加‘else’,推测‘else’应该是在最后一个条件前加,否则报错
        when score >= 60 and score < 85 then 'pass' else # 此处需要加‘else’或者下面继续用‘when...then'
        'good'
    end
    )as 'rank'
from
    score;

查询结果如下:

sid cid score rank
01  01  80  pass
01  02  90  good
01  03  99  good
02  01  70  pass
02  02  60  pass
02  03  80  pass
03  01  80  pass
03  02  80  pass
03  03  80  pass
04  01  50  fail
04  02  30  fail
04  03  20  fail
05  01  76  pass
05  02  87  good
06  01  31  fail
06  03  34  fail
07  02  89  good
07  03  98  good

(2)考察点:复杂查询—多表非连接查询
简单原表:

sid cid score
01  01  80
01  02  90
01  03  99
02  01  70
02  02  60

求各score占比:
a)该表中分数(score)各不相同,因此不需用到分组函数

SELECT
    a.score,
    concat( round( a.score / b.total * 100, 2 ), ' %' ) AS percent # 连接-四舍五入-计算占比
FROM
    ( SELECT * FROM score LIMIT 5 ) a, # a表为原始的待计算数据表
    ( SELECT sum( score ) total FROM ( SELECT * FROM score LIMIT 5 ) a ) b # b表为计算占比的总和参数
ORDER BY
    score DESC;
score percent
99  24.81 %
90  22.56 %
80  20.05 %
70  17.54 %
60  15.04 %

b)该表中分数(score)有相同,因此需用到分组求和函数

SELECT
    tt.rank,
    concat(round(tt.rank_num / b.total * 100,2),' %') as percent 
FROM
    (
SELECT
    t.rank,
    count( * ) rank_num 
FROM
    (
SELECT
    *,
    ( CASE WHEN score < 60 THEN 'fail' # 注意此处不需要加‘else’,推测‘else’应该是在最后一个条件前加,否则报错
    WHEN score >= 60 AND score < 85 THEN 'pass' ELSE # 此处需要加‘else’或者下面继续用‘when...then'
    'good' END ) AS 'rank' 
FROM
    score 
    ) t 
GROUP BY
    t.rank 
    ) tt,
    (
SELECT
    sum( rank_num ) total 
FROM
    (
SELECT
    t.rank,
    count( * ) rank_num 
FROM
    (
SELECT
    *,
    ( CASE WHEN score < 60 THEN 'fail' # 注意此处不需要加‘else’,推测‘else’应该是在最后一个条件前加,否则报错
    WHEN score >= 60 AND score < 85 THEN 'pass' ELSE # 此处需要加‘else’或者下面继续用‘when...then'
    'good' END ) AS 'rank' 
FROM
    score 
    ) t 
GROUP BY
    t.rank 
    ) tt 
    ) b;
rank percent
fail    27.78 %
good    27.78 %
pass    44.44 %

该方法可行,但过程繁琐,调用了两次原始表。
c)简单方式

set @sum = (select sum(score) from score); # 定义一个参数即可
select score,concat(round(score / @sum * 100,2),'%') as percent from score;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 网上流传较广的50道SQL训练,奋斗了不知道多久终于写完了。前18道题的难度依次递增,从19题开始的后半部分算是循...
    Kaidi_G阅读 477,618评论 312 452
  • 50个常用的sql语句Student(S#,Sname,Sage,Ssex) 学生表Course(C#,Cname...
    哈哈海阅读 1,261评论 0 7
  • 说明:以下五十个语句都按照测试数据进行过测试,最好每次只单独运行一个语句。 问题及描述: --1.学生表 Stud...
    lijun_m阅读 1,337评论 0 1
  • Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 S...
    忘了呼吸的那只猫阅读 2,940评论 0 8
  • 有一种职业,不是民警,却要每天解决争抢纠纷;有一种职业,不是医生,却要了解各类疑难杂症;有一种职业,不是文秘,却要...
    陈春燕8286阅读 506评论 0 0