如何在不使用内部查询的情况下从表中选择第二和第三高薪的差异

时间:2017-09-01 19:55:47

标签: mysql sql oracle

假设我们有一个名为emp的表,其中只有一个名为salary的列只有6行。

我希望得到的结果(第二高和第三高薪的差异)和(第四高和第五高薪的差异)。

注意:我不想对此使用任何内部查询。所以请帮我写这个查询?

提前致谢

Please find table below : (this table is not in sorted order)

    |Salary|
    --------
    |150000|
    |130000|
    |140000|
    |160000|
    |180000|
    |190000|

我已经写了以下查询给出了数据,但由于数据不是按排序顺序所以我面临的问题

ABS(ABS((select salary
        from EMP where rownum <3 minus select salary from EMP
        where rownum <2 )-
    (select salary
        from EMP where rownum <2 minus select salary from EMP
        where rownum <1))-
    ABS((select salary
        from EMP where rownum <5 minus select salary from EMP
        where rownum <4 )-
    (select salary
    from EMP where rownum <4 minus select salary from EMP
    where rownum <3 )))

2 个答案:

答案 0 :(得分:4)

Oracle

很难没有子查询...除非你正在寻找真正丑陋和低效的代码。

使用match_recognize子句,在Oracle 12.1及更高版本中,这是一种不使用子查询的简洁方法:

with
     emp ( salary ) as (
       select 150000 from dual union all
       select 130000 from dual union all
       select 140000 from dual union all
       select 160000 from dual union all
       select 180000 from dual union all
       select 190000 from dual
     )
-- End of simulated inputs (for testing only, not part of the solution!)
-- SQL query begins BELOW THIS LINE.
select result
from   emp
match_recognize (
  order by salary desc
  measures (b.salary - c.salary) + (d.salary - e.salary) as result
  one row per match
  pattern ( ^ a b c d e )
  define  a as 0 = 0
)
;

RESULT
------
 30000

这是一种基本的(和愚蠢的!)方式:

select max(e2.salary) - max(e3.salary) + max(e4.salary) - max(e5.salary) as result
from   emp e1 join emp e2 on e1.salary > e2.salary
              join emp e3 on e2.salary > e3.salary
              join emp e4 on e3.salary > e4.salary
              join emp e5 on e4.salary > e5.salary
;

答案 1 :(得分:2)

您可以使用NTH_VALUE Oracle功能。

SELECT distinct ((NTH_VALUE(salary, 2) OVER (ORDER BY salary DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) - 
                 (NTH_VALUE(salary, 3) OVER (ORDER BY salary DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING))) +
                ((NTH_VALUE(salary, 4) OVER (ORDER BY salary DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) - 
                 (NTH_VALUE(salary, 5) OVER (ORDER BY salary DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)))
FROM emp