3

我想写一个查询来显示获得前 3 名薪水的员工

  SELECT *
    FROM (SELECT salary, first_name
            FROM employees
        ORDER BY salary desc)
   WHERE rownum <= 3;

但我不明白这个 rownum 是如何计算嵌套查询的,如果它有问题,请让我理解:

SELECT *
  FROM (SELECT salary, first_name 
          FROM employees
      ORDER BY salary )
 WHERE rownum >= 3;

我浏览了这个链接Oracle/SQL: Why does query "SELECT * FROM records WHERE rownum >= 5 AND rownum <= 10" - return zero rows,但它再次指向一个链接,它没有给出答案

4

8 回答 8

6

a_horse_with_no_name 的答案很好,
但只是为了让您了解为什么您的第一个查询有效而您的第二个查询无效:

当您使用子查询时,Oracle 不会神奇地使用子查询的 rownum ,它只是获取排序的数据,因此它相应地给出 rownum,匹配条件的第一行仍然获得 rownum 1,依此类推。这就是为什么您的第二个查询仍然不返回任何行的原因。

如果要限制起始行,则需要保留子查询的rownum,即:

SELECT *
FROM (SELECT * , rownum rn
  FROM (SELECT salary, first_name
          FROM employees
      ORDER BY salary ) )sq
WHERE sq.rn >= 3;

但正如 a_horse_with_no_name 所说,有更好的选择......

编辑:为了让事情更清楚,看看这个查询:

with t as (
select 'a' aa, 4 sal from dual
union all
select 'b' aa, 1 sal from dual
union all
select 'c' aa, 5 sal from dual
union all
select 'd' aa, 3 sal from dual
union all
select 'e' aa, 2 sal from dual
order by aa
)
select sub.*, rownum main_rn 
  from (select t.*, rownum sub_rn from t order by sal) sub 
 where rownum < 4

注意sub rownum和main rownum的区别,看哪个用于criteria

于 2012-04-15T08:16:25.000 回答
4

查询的“rownum”在order by 应用于结果之前分配。所以 rownumw 42 可能会成为第一行。

一般来说,您需要使用内部查询中的 rownum 来限制您的整体输出。这在手册中有很好的解释:

http://docs.oracle.com/cd/E11882_01/server.112/e26088/pseudocolumns009.htm#i1006297

我更喜欢使用 row_number() 代替,因为您可以更好地控制排序,而且它是适用于大多数现代 DBMS 的标准功能:

SELECT *
FROM (
  SELECT salary, 
         first_name, 
         row_number() over (order by salary) as rn
  FROM employees
)
WHERE rn <= 3
ORDER BY salary;

您应该了解,在这种情况下,派生表只需要能够对生成的rn列应用条件。它不能避免“rownum 问题”,因为 的值row_number() 取决于over(...)部件中指定的顺序(它独立于应用于查询本身的任何排序)

请注意,这不会返回具有相同薪水且仍属于前三名的员工。在这种情况下,使用dense_rank()可能更合适。

于 2012-04-15T07:47:35.490 回答
0

如果你想选择薪水前三名的人..也许你应该考虑使用分析..更像

SELECT *
FROM (
    SELECT salary, first_name, dense_rank() over(order by salary desc) sal_rank
    FROM employees 
)
WHERE  sal_rank <= 3

即所有具有第三高(排名)工资金额(或更多)的人

与使用普通 rownum 相比,这样做的好处是,如果您有多个薪水相同的人,他们都将被退回。

于 2013-05-02T05:38:09.693 回答
0

打印第五高薪水的最简单方法。

SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 5 

根据相同,如果您想打印第三或第四高薪水,则只需更改最后一个值。(意味着使用 3 或 4 而不是 5,您将获得第三或第四高薪水)。

SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 4

SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 3
于 2013-08-26T19:17:05.337 回答
0

SELECT EMPNO, SAL, (SELECT SUM(E.SAL) FROM TEST E WHERE E.EMPNO <= T.EMPNO) R_SAL FROM (SELECT EMPNO, SAL from TEST ORDER BY EMPNO) T

于 2013-08-30T10:36:17.100 回答
0

返回所有字段详细信息的 oracle 中查找前 3 名员工的最简单方法:

SELECT *
FROM (
    SELECT * FROM emp  
      ORDER BY sal DESC)
WHERE rownum <= 3 ;
于 2013-09-20T02:11:33.363 回答
0
select * 
from (
    select emp.*, 
           row_number() over(order by sal desc)r 
    from emp
) 
where r <= 3;
于 2015-01-22T08:58:55.467 回答
0
SELECT Max(Salary)
FROM Employee
WHERE Salary < (SELECT Max(salary) FROM employee WHERE Salary NOT IN (SELECT max(salary) FROM employee))
ORDER BY salary DESC;
于 2018-08-15T12:32:10.917 回答