zoukankan      html  css  js  c++  java
  • 排序拿到第N个结果的问题

    场景:

    例如成绩,需要得到第二名的同学的名字;或者例如薪水,想要查询到薪水第三高的员工的名字;类似种种问题,做个总结。

    ———————————————————————————

    1.Oracle语境

    Oracle语境下,这里按照成绩为例先建表。

    create table test_data(
           id varchar2(32),
           name varchar2(32),
           score float
    )
    
    insert into test_data values('xxx1', '小明', 97);
    insert into test_data values('xxx2', '小军', 93);
    insert into test_data values('xxx3', '小红', 97);
    insert into test_data values('xxx4', '小黑', 95);

    查询得到数据如下:

    (4行被选择)

     我们想要得到目前小黑排名第二的成绩,考虑到Oracle提供一个rownum的属性,我Order by一下然后取rownum为2不就行了嘛,于是可以得到如下sql:

    select name
      from (select t.* from test_data t order by t.score desc)
     where rownum = 2

    得到结果:

     (0行被选择)

    诶?这是为什么呢?我明明先进行了排序,然后取rownum为2不就应该查出来小黑的数据嘛?

    这里我查询了一下Oracle的rownum属性,其实是一个很神奇的属性,它是对于每一条数据进行比对的,比如这里选择了rownum = 2,其实每一行的rownum都是1,所以并不会得到想要的结果。详细的解释见https://blog.csdn.net/haijiege/article/details/78856307

    如何解决?——取一个别名

    对没错,就是取一个别名,如下:

    select name
      from (select name, rownum rn
              from (select t.* from test_data t order by t.score desc))
     where rn = 2

    这样查询到的结果为:

    (1行被选择)

     诶?我明明想得到小黑的名字,怎么会得到小红的呢?其实这里存在一个相同元素排序的问题,由于前面两个人成绩都是97,所以排在第二位的也是97的小红(id小明的ASCII码稍微比小红的小一些),这种情况该怎么解决呢?

    这就需要对于每一行的成绩进行比对了,查询大于目前该行成绩结果的总行数作为目前的排名,可以得到如下SQL:

    select name
      from (select name,
                   (select count(distinct score)
                      from test_data
                     where score >= s.score) as rn
              from test_data s
             order by score desc)
     where rn = 2

    查询结果:

    (1行被选择)

     这样就可以得到预期结果啦!

    2.Mysql语境

    思路大致与上述相同,只不过语句不太一样,这里使用存储过程(函数)来说明

    CREATE FUNCTION getNthScore ( n INT ) RETURNS INT 
    BEGIN
    SET n = n - 1;
    RETURN ( 
      SELECT NAME FROM test_data WHERE score = ( SELECT DISTINCT score FROM test_data ORDER BY score DESC LIMIT n, 1 ) 
    );
    END

    按照limit查询排名第几的成绩,然后反向去查找对应的名字

    这样输入n=2,查询得到结果为:

    (第1条记录,共1条)

    ———————————————————————————

    至此!

  • 相关阅读:
    函数作业1
    函数、装饰器、迭代器、内置方法总练习题
    疑问
    装饰器
    文件练习题1,2
    内置函数练习题和总结
    GET和POST请求的区别
    HTTP请求方法
    HTTP之状态码
    HTTP之响应消息Response
  • 原文地址:https://www.cnblogs.com/doona-jazen/p/12004737.html
Copyright © 2011-2022 走看看