明确题意:
找到每类试卷得分的前3名,如果两人最大分数相同,选择最小分数大者,如果还相同,选择uid大者。
问题拆解:
- 本题主要是考察知识点:row_number、group by等
- 先join,后group by uid,找到最大值、最小值
- 使用row_number排序,语法ROW_NUMBER() OVER (<partition_definition> <order_definition>),row_number遇到同分的也是顺序排名,rank()是1,2,2,4这样跳跃排名。
- 取rank_num<=3的记录。此时需要套一个子表,如果是row_number之后再在where中直接取排名会报错!!(执行顺序的原因,见下文)
代码实现:
select * from ( select tag, uid, row_number() over (partition by tag order by tag,max_score desc,min_score desc,uid desc) as rank_num -- 不能写成rank,rank是关键字,会报错 from ( select t1.tag, t2.uid, max(score) as max_score, min(score) as min_score from examination_info t1 join exam_record t2 on t1.exam_id = t2.exam_id group by t1.tag, t2.uid ) t1 )t2 where rank_num <= 3 ;
为何会报错?
1 如果是row_number之后再在where中直接取排名,为何会报错?
比如:
select tag, uid, row_number() over (partition by tag order by tag,max_score desc,min_score desc,uid desc) as rank_num -- 不能写rank from ( ... ) t1 where rank_num <= 3 ;select语句是先执行from再执行where最后select..所以当执行到where的时候from出来的结果集里并没有row_number()字段,所以报错!
2 如果把row_number表达式放在where,为何会报错?
比如:
select * from ( select tag, uid, row_number() over (partition by tag order by tag,max_score desc,min_score desc,uid desc) as rank_num -- 不能写rank from ( ... ) t1 )t2 where row_number() over (partition by tag order by tag,max_score desc,min_score desc,uid desc) <= 3 ;
报错:SQL_ERROR_INFO: "You cannot use the window function 'row_number' in this context.'"
窗口函数是在from...where....之后(数据已经准备好之后)才执行,而在where中执行窗口函数会由于数据还没准备好就开窗会报错。
不足之处,欢迎指正。