题解 | #对试卷得分做min-max归一化#

对试卷得分做min-max归一化

http://www.nowcoder.com/practice/2b7acdc7d1b9435bac377c1dcb3085d6

一、知识点总结与拓展

 本题所涉及到的知识点不多,困难点在于题目读起来比较拗口,以及一些关键信息藏在“解释”里。牛客的题,好多线索都喜欢放在“解释”里。
主要考察聚类窗口函数,和聚类窗口函数的用法和GROUP BY 函数类似。
  • MIN()OVER() :不改变表结构的前提下,计算出最小值
  • MAX()OVER():不改变表结构的前提下,计算出最大值
  • COUNT()OVER():不改变表结构的前提下,计数
  • SUM()OVER():不改变表结构的前提下,求和
  • AVG()OVER():不改变表结构的前提下,求平均值
在我的理解窗口函数的关键词是“不改变表格结构”,查出的数据,单独放一列

二、题目解读与解题步骤拆分

1、题目解读

题目:请你将用户作答高难度试卷的得分在每份试卷作答记录内执行min-max归一化后缩放到[0,100]区间,并输出用户ID、试卷ID、归一化后分数平均值;最后按照试卷ID升序、归一化分数降序输出。(注:得分区间默认为[0,100],如果某个试卷作答记录中只有一个得分,那么无需使用公式,归一化并缩放后分数仍为原分数)。

题目中隐藏的坑

坑1:某个试卷作答记录中只有一个得分,那么无需使用公式
坑2:归一化后分数平均值取整数(取自解释中的这句话“后两个得分都是用户1001作答的,因此用户1001对试卷9001的新得分为(95+100)/2≈98(只保留整数部分)”),因而,需要对同一个用户的归一化分数取平均值。
所以,做题一定要看“解释”的内容

需求字段

  • uid
  • exam_id
  • avg_new_score 最终归一结果

 

2、步骤拆分

1)用户作答高难度试卷的得分

  • 关联两张表,取difficulty='hard' 的数据

2)在每份试卷作答记录内执行min-max归一化

  • 归一化公示:min(score),max(score)
  • (score-min(score))/(max(score)-min(score))

3)如果某个试卷作答记录中只有一个得分,那么无需使用公式

  • 当min(score)=max(score)那就说明只有一个得分

4)归一化后缩放到[0,100]区间

  • 归一化结果*100

5)归一化后分数平均值取整数

6)按照试卷ID升序、归一化分数降序输出。

三、步骤代码

1)关联两张表,取difficulty='hard' 的数据,找出每类试卷的最小值和最大值

SELECT uid,a.exam_id,score,
    MIN(score) OVER(PARTITION BY exam_id) min_x, #求每类试卷的得分最小值
    MAX(score)OVER(PARTITION BY exam_id) max_x #求每类试卷的得分最大值
FROM exam_record a
LEFT JOIN examination_info b ON a.exam_id=b.exam_id
WHERE difficulty='hard' #难度为'hard'
AND score IS NOT NULL; #分数不为空

 

2)在每份试卷作答记录内执行min-max归一化

  • (score-min(score))/(max(score)-min(score))
  • 如果某个试卷作答记录中只有一个得分,那么无需使用公式,当min(score)=max(score)那就说明只有一个得分
  • 区间为[0-100],归一化结果*100

SELECT exam_id,uid,score,
	IF(min_x=max_x,score,(score-min_x)*100/(max_x-min_x))max_min #如果某试卷只有一个得分,不用公式
FROM (
		SELECT uid,a.exam_id,score,
		MIN(score) OVER(PARTITION BY exam_id) min_x, #求每类试卷的得分最小值
		MAX(score)OVER(PARTITION BY exam_id) max_x #求每类试卷的得分最大值
		FROM exam_record a
		LEFT JOIN examination_info b ON a.exam_id=b.exam_id
		WHERE difficulty='hard' #难度为'hard'
		AND score IS NOT NULL #分数不为空
	)t1


3)归一化后分数平均值取整数

  •  ROUND(SUM(max_min)/COUNT(max_min),0) avg_new_score

6)按照试卷ID升序、归一化分数降序输出。
ORDER BY exam_id,avg_new_score DESC
7)完整代码

SELECT uid,exam_id,
ROUND(SUM(max_min)/COUNT(max_min),0) avg_new_score
FROM (
	SELECT exam_id,uid,score,
	IF(min_x=max_x,score,(score-min_x)*100/(max_x-min_x))max_min/*如果某试卷只有一个得分*/
	FROM (
		SELECT uid,a.exam_id,score,
		MIN(score) OVER(PARTITION BY exam_id) min_x, #求每类试卷的得分最小值
		MAX(score)OVER(PARTITION BY exam_id) max_x #求每类试卷的得分最大值
		FROM exam_record a
		LEFT JOIN examination_info b ON a.exam_id=b.exam_id
		WHERE difficulty='hard' #难度为'hard'
		AND score IS NOT NULL #分数不为空
		)t1
		
	)t2

GROUP BY exam_id,uid
ORDER BY exam_id,avg_new_score DESC;#按照试卷ID升序,评价分降序排序

SQL解题集 文章被收录于专栏

这是牛客SQL相关的解题集

全部评论
姐姐你是我的神!!(女生)
5 回复 分享
发布于 2022-05-24 16:41
这是我见过最详细的了
2 回复 分享
发布于 2022-07-08 16:11
为什么我总是卡在理不清题意那里啊?大神有什么理清题意的思考方式吗?还是说题刷个10遍20遍的就慢慢能理清了?
1 回复 分享
发布于 2023-12-10 21:46 四川
SQL我只看盐甜甜
1 回复 分享
发布于 2023-07-30 23:15 广东
最后的sum可以直接用avg函数
1 回复 分享
发布于 2023-07-15 16:14 上海
代码:select exam_id,(score-min(score))/(max(score)-min(score)) mmx from exam_record left join examination_info using(exam_id) where difficulty='hard' and score is not null group exam_id 问题:这样求归一化分数为什么总会报错呢?
1 回复 分享
发布于 2023-02-05 10:15 北京
说最大值最小值相等就说明只有一个得分,万一几次多分都是一样的呢
1 回复 分享
发布于 2022-08-02 17:30
牛,怎么做到这么条理清晰的
1 回复 分享
发布于 2022-05-26 16:56
大佬, 看了你很多题解,这次我居然和你思路一模一样,成功写出来了,太谢谢啦!!!
点赞 回复 分享
发布于 2024-05-23 15:48 河北
牛逼啊
点赞 回复 分享
发布于 2023-09-10 17:57 陕西
请问为啥IF(min_x=max_x,score,(score-min_x)*100/(max_x-min_x)),我用case when min_x=max_x then score then (score-min_x)*100/(max_x-min_x) end as max_min代替会报错呢
点赞 回复 分享
发布于 2023-03-30 15:33 上海
姐姐牛逼,我们题干理解的一知半解,一看你解释就豁然开朗
点赞 回复 分享
发布于 2023-03-13 11:36 广东
姐姐又是你,回来看自己之前压根没看懂的题目,发现还是看不懂,全靠姐姐的题解了!姐姐你是我滴神!已关注,嘻嘻。
点赞 回复 分享
发布于 2022-12-17 15:02 上海
IF(min_x=max_x,score,(score-min_x)*100/(max_x-min_x))max_min 如果只有一个分数,则返回值为对应的分数值,为什么会直接i变成0
点赞 回复 分享
发布于 2022-09-14 10:28 湖南

相关推荐

点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
105
16
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务