计算多个最高和最低列值的差值

Calculate difference of multiple highest and lowest column values

我有一个 table 这样的:

id | name | salary
------------------
1  | guy1 | 1000
2  | guy2 | 750
3  | guy3 | 400
4  | guy4 | 1000
5  | guy5 | 925
6  | guy6 | 900

我需要取最高薪水(在本例中为 2 * 1000)和最低薪水(在本例中为 1 * 400),return 最高薪水和最低薪水的差额计算如下:

1000 * 2 - 400 * 1 = 1600

difference
----------
1600

我尝试筛选出工资最高和最低的 table 但失败了。

如果 table 为空,则结果应为 0。

你可以这样做:

select
  (select sum(salary) from t where salary = (select max(salary) from t))
  -
  (select sum(salary) from t where salary = (select min(salary) from t));

结果:

1600

请参阅 DB Fiddle 中的 运行 示例。

您可以使用 dense_rank 找到最低和最高薪水,然后自行加入这些结果,对它们求和并减去:

SELECT SUM(CASE sal_desc WHEN 1 THEN salary END) - 
       SUM(CASE sal_asc WHEN 1 THEN salary END)
FROM   (SELECT salary, 
               DENSE_RANK() OVER (ORDER BY salary ASC)  AS sal_asc,
               DENSE_RANK() OVER (ORDER BY salary DESC) AS sal_desc
        FROM   mytable) t

一种方法是聚合两次:

select sum(case when seqnum_desc = 1 then sum_salary
                else - sum_salary
           end) as diff
from (select salary, sum(salary) as sum_salary,
             row_number() over (order by salary asc) as seqnum_asc,
             row_number() over (order by salary desc) as seqnum_desc
      from t
      group by salary
     ) t
where 1 in (seqnum_asc, seqnum_desc)

Postgres 13 添加了 WITH TIES 子句以包括第 n 行的所有对等点:

如果您在 salary 上有索引,这将快到。比涉及 window 函数快得多:

SELECT COALESCE(sum(salary), 0) AS diff
FROM  (
   (  -- parentheses required
   SELECT salary
   FROM   tbl
   ORDER  BY salary DESC
   FETCH  FIRST 1 ROWS WITH TIES
   )
   UNION ALL
   (
   SELECT salary * -1
   FROM   tbl
   ORDER  BY salary
   FETCH  FIRST 1 ROWS WITH TIES
   )
   ) sub;

db<>fiddle here

Postgres 可以直接从 (salary) 上的索引中获取第一个和最后一个值。准瞬时结果,无论 table 有多大。

当 table 为空时,

COALESCE() 得到 0 而不是 NULL

为什么要加括号? The manual:

(ORDER BY and LIMIT can be attached to a subexpression if it is enclosed in parentheses. Without parentheses, these clauses will be taken to apply to the result of the UNION, not to its right-hand input expression.)

参见:

这是假设 salaryNOT NULL,否则将 NULLS LAST 添加到降序。参见:

  • Sort by column ASC, but NULL values first?