使用Partition by的SQL中最高和最高工资之间的差异

时间:2016-12-20 18:39:46

标签: sql postgresql window-functions

我有这样的数据:

CREATE TABLE salaries AS
SELECT * FROM ( VALUES
  ('US'    , 'A', 3935),
  ('US'    , 'B', 7805),
  ('US'    , 'C', 2302),
  ('US'    , 'D', 6772),
  ('US'    , 'E', 3173),
  ('US'    , 'F', 7739),
  ('Japan' , 'G', 3881),
  ('Japan' , 'H', 1158),
  ('Japan' , 'I', 2591),
  ('Japan' , 'J', 3758),
  ('Japan' , 'K', 8710),
  ('Japan' , 'L', 3376),
  ('France', 'M', 5768),
  ('France', 'N', 9466),
  ('France', 'O', 1750),
  ('France', 'P', 1049),
  ('France', 'Q', 3479),
  ('France', 'R', 5305)
) AS t(country,employee,salary);

为了找出每个国家的最高工资和第五高工资之间的差异,我正在尝试以下方法:

select max(salary) over (partition by country) - rank(5) over (partition by country) 
from salaries

但它引发了以下错误:

“有序集合函数”需要“WITHIN GROUP”

任何人都可以在不使用任何联接的情况下建议任何方法吗?

4 个答案:

答案 0 :(得分:2)

  1. 创建一个WINDOW,用于定义您想要的内容(按国家/地区分区,按工资下降顺序排列)
  2. 计算该窗口上的max(salary)
  3. 从顶部计算nth_value(因为它们按工资降序排序)
  4. 特别说明WINDOWS有范围和行。它们详细说明了如何在该窗口中执行计算。在这里,我们必须使WINDOW取消nth_value()以使SELECT * , max(salary) OVER w1 - nth_value(salary,5) OVER w1 AS max_minus_fifth_highest FROM foo WINDOW w1 AS ( PARTITION BY (country) ORDER BY SALARY desc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) ORDER BY country; 起作用。通常情况下,它会根据所看到的所有内容进行计算,因此nth_value只有在看到该行时才会启动 - 但我们可以让它看到前方。

    代码,

    display: block;

    Sql Demo

答案 1 :(得分:2)

select      country
           ,max(salary) - max(case dr when 5 then salary end) as salary_diff

from       (select      country     
                       ,salary
                       ,dense_rank() over (partition by country order by salary desc) as dr

            from        salaries
            ) s

group by    country            

答案 2 :(得分:0)

select country, max_sal - salary
from (
     select country, salary, 
            max(salary) over (partition by country) max_sal,
           case when (row_number() over (partition by country
                                         order by salary desc)) = 5 
                then 1 
           end fifth
from table
) t where fifth is not null;

答案 3 :(得分:0)

<强> SQL DEMO

with fifth as (
     SELECT country, "salary",
            rank() over (partition by "country" order by "salary" desc)  rnk
     FROM salaries
)
SELECT *
FROM salaries s
JOIN fifth f
  ON s.country = f.country
 AND f.rnk = 5

输出

enter image description here