明确题意:

找到每类试卷得分的前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()字段,所以报错!

如果把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中执行窗口函数会由于数据还没准备好就开窗会报错。

不足之处,欢迎指正。