计算多个最高和最低列值的差值
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.)
参见:
这是假设 salary
是 NOT NULL
,否则将 NULLS LAST
添加到降序。参见:
- Sort by column ASC, but NULL values first?
我有一个 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 有多大。
COALESCE()
得到 0
而不是 NULL
。
为什么要加括号? The manual:
(
ORDER BY
andLIMIT
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 theUNION
, not to its right-hand input expression.)
参见:
这是假设 salary
是 NOT NULL
,否则将 NULLS LAST
添加到降序。参见:
- Sort by column ASC, but NULL values first?