select * from c where salary in(从工资desc组中选择工资来自rownum工资的rownum = 2);

时间:2017-10-06 06:19:30

标签: sql oracle

我想从这个查询获得第二高薪

SELECT *
FROM c
WHERE salary IN (
        SELECT salary
        FROM c
        ORDER BY salary DESC
        GROUP BY rownum salary
        HAVING rownum = 2
        );
  

错误:缺少表达

2 个答案:

答案 0 :(得分:2)

您可以在此处使用排名分析功能,例如

SELECT salary
FROM
(
    SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) dr
    FROM c
) t
WHERE dr = 2;

这将按密集排名返回第二高薪,包括所有第二高的薪水。

答案 1 :(得分:0)

解释为什么子查询无法工作:

  1. 首先,以任意顺序从表中读取记录。这是他们获得rownum
  2. 的时候
  3. 然后聚合发生;一个salary的所有记录都会压缩为一行。您以前单行的rownum不再可用。
  4. 然后,汇总的行按HAVING进行过滤,但这不起作用,因为您尝试访问rownum。此外,rownum = 2上的条件总是失败,因为你正在解雇第一行,所以它是&#34;不读&#34;并且rownum 1仍然可用,你关闭第二个,因为你还没有阅读rownum 1,依此类推。 rownum上的标准始终为rownum <= some_number(除了1,您可以rownum = 1)。
  5. 最后发生的事情是排序;因此,ORDER BY子句属于查询的末尾。 (从Oracle 12c开始,它只能跟FETCH FIRST n ROWS。)
  6. 以下是如何使其与rownum

    一起使用
    select salary
    from
    (
      select salary
      from
      (
        select distinct salary 
        from c
        order by salary desc
      )
      where rownum <= 2
      order by salary
    )
    where rownum = 1;
    

    这很有效,因为Oracle在这里违反了SQL标准。根据该标准,子查询中的数据被认为是无序的,但Oracle在使用rownum时保证了订单。

    以下是使用聚合的方法:

    select max(salary) from c where salary < (select max(salary) from c);
    

    从Oracle 10开始,您还可以使用分析函数,如Tim的回答所示。