结算日月分组条件如何写_图解面试题:如何分组比较?

778220538847d4ba50558bba97b57be1.png

【题目】

现有“成绩表”,记录了每个学生各科的成绩。表内容如下:

bf3d4553a6a94acd5544397f23a0d3f9.png

问题:查找单科成绩高于该科目平均成绩的学生名单

【解题思路】

1."查找单科成绩高于该科目平均成绩",也就是在“每个”科目里比较。还记得我们之前课程里讲过的吗?当有“每个”出现的时候,就要想到是要分组了。

能实现“分组”功能的sql有两种,一是group by字句,另一个是窗口函数的partition by。

2.使用聚合窗口函数(求平均值avg),将每门课的平均成绩求出以后,然后找出大于比平均成绩的数据。

这就要求分组后不能减少表的行数。

group by分组汇总后改变了表的行数,一行只有一个类别。而partiition by和rank函数不会减少原表中的行数。例如下面统计每个班级的人数。

03d031f64f65ce3742dce8135d7c42a9.png

所以这里我们使用使用窗口函数的partition by。

【解题步骤】

第1步,聚合函数avg()作为窗口函数,将每一科目成绩的平均值求出。sql语句如下:

select *, 
       avg(成绩) over (partition by 科目) as avg_score
from 成绩表;

运行结果如下:

bfa327f043a4b4de0b8a6028af194432.png

第2步,如上表,按科目分组后各科目的平均分已经计算出,接下来只要筛选出成绩大于平均分的数据即可。

那么,只需要在上一步的slq语句里加入条件字句where就可以了

select *, 
       avg(成绩) over (partition by 科目) as avg_score
from 成绩表
where 成绩 > avg_score;

很多同学都会用这样的思路解题,但是这样写,sql会报错,为什么呢?

我们在《从零学会sql》里多次强调过,要牢记sql的书写顺序和运行顺序。在运行顺序中,select字句是最后被运行的。

a8fe7187483fe2452c1cc710660ee26c.png

当明白了运行顺序以后,就知道错误的原因了:运行到”where ranking > 2”的时候,因为select字句还没有被执行,因此select中的“ranking”列还没有出现,从而导致报错。

解决方法是什么呢?

这种情况就可以用子查询,也就是把第一步得到查询结果作为一个新的表,sql语句如下:

select *
from (select *, 
             avg(成绩) over (partition by 科目) as avg_score
      from 成绩表) as b
where 成绩 > avg_score;

运行结果如下:

f7f190fa35a5bf6a59918d05a8e43594.png

【本题考点】

1.主要考查对窗口函数的灵活使用。

2.在筛选过程中,非常容易因为子查询问题报错,本题也考察了对子查询的熟练运用。

3.本题间接考察了对sql语句执行顺序的熟悉程度。

【举一反三】

在“每个组里比较”的问题,比如查找每个组里大于平均值的数据,可以有两种方法:

1)使用上面讲到的窗口函数来实现

2)使用关联子查询,可以回顾《从零学会sql:复杂查询》里的案例

6a11106183dba564b316e212d596d7ae.png

推荐:如何从零学会SQL?

7ee8677a4a3558485859f02dc56f07d4.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值