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条)

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

    至此!

  • 相关阅读:
    “连城决”——预示2008年手机营销体式格式新打破
    都会演出连城诀—诺基亚N78决战入手入手了!
    Lyx:阔别单调的 LaTeX 节制命令
    [转载]Oracle 11g R1下的自动内存经管(2)
    假造化手艺是决胜企业IT化的关头
    请各位博友对HyperV的运用终了指摘
    有199元的Office,还要用盗版吗?
    十一回南通,当晚和同学去小石桥附近的网吧
    Windows 消息
    WinAPI: 钩子回调函数之 MsgFilterProc
  • 原文地址:https://www.cnblogs.com/doona-jazen/p/12004737.html
Copyright © 2011-2022 走看看