假设一个表salaries包含employee_id、department_id和salary,如下。
e_id | dpt_id | salary
---- | ------ | ------
1 | 2 | 1000
2 | 2 | 2000
3 | 5 | 3000
4 | 6 | 500
5 | 5 | 100
6 | 1 | 1050
我想为 dpt 提供最高/最低工资,我使用了以下查询,但失败了:
select sum_sal_per_dpt.dpt_id, max(sum_sal_per_dpt.total_salaries)
from (
select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id ) as sum_sal_per_dpt
group by sum_sal_per_dpt.dpt_id
union
select sum_sal_per_dpt.dpt_id, min(sum_sal_per_dpt.total_salaries)
from (
select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id ) as sum_sal_per_dpt
group by sum_sal_per_dpt.dpt_id
我得到的输出是一个包含 dpt_id 和工资总和的表,就好像只执行了子查询一样:
dpt_id | salary
------ | ------
2 | 3000
5 | 3100
6 | 500
1 | 1050
而不是
dpt_id | salary
------ | ------
5 | 3100
6 | 500
如果我以 CTE 方式编写它,也是一样的。
with
sum_sal_per_dpt as (select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id)
select sum_sal_per_dpt.dpt_id, max(sum_sal_per_dpt.total_salaries)
from sum_sal_per_dpt
group by sum_sal_per_dpt.dpt_id
union
select sum_sal_per_dpt.dpt_id, min(sum_sal_per_dpt.total_salaries)
from sum_sal_per_dpt
group by sum_sal_per_dpt.dpt_id
有人可以解释一下吗?
与鲍里斯·约万诺维奇的答案基本相同,只是没有工会。
with
sum_sal_per_dpt as (select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id)
SELECT dpt_id, total_salaries
FROM sum_sal_per_dpt
WHERE
total_salaries = ( SELECT max(total_salaries) FROM sum_sal_per_dpt )
OR
total_salaries = ( SELECT min(total_salaries) FROM sum_sal_per_dpt );
结果:
dpt_id | 总工资 |
---|---|
5 | 3100 |
6 | 500 |
您总是会退回到使用“GROUP BY”并指示 DBMS 按 dpt_id 聚合您的结果。 所以它永远不会整理任何部门 ID。
Max(XYZ) 不是一个过滤/聚合函数,只能为您提供列的最大值以及该最大值的所有相应字段。
它将为您提供每个不同行的最大值 - 其中区别是由您在 GROUP BY 子句
如果您将第一个查询更改为仅给出最大/最小值,您可以看到这些值已经存在 - 只是无法使用。
select max(sum_sal_per_dpt.total_salaries), min(sum_sal_per_dpt.total_salaries)
from (
select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id ) as sum_sal_per_dpt
最大 | 分钟 |
---|---|
3100 | 500 |
我刚刚应用了官方 postgres 文档中的聚合门教程中的解决方案。
Postgres 聚合文档
以下内容应该会给您带来预期的结果:
;with data as
(
select dpt_id, sum(salary) as total_salaries
from salaries
group by dpt_id
)
select dpt_id, total_salaries
from data
where total_salaries = (select max(total_salaries) from data)
union
select dpt_id, total_salaries
from data
where total_salaries = (select min(total_salaries) from data)
请注意,如果您有多个最大值和/或最小值,上面的代码将为您提供多行,您可以根据您想要看到的内容轻松调整它。
在您的代码中,您使用的是
dpt_id
分组,这就是为什么您仍然获得每个 dpt_id
的最大值,因此多行,使用 union
而不是 union all
可能会造成额外的混乱,这将删除两个表中相同的行。
您可以使用
ROW_NUMBER()
来识别行。然后过滤就很容易了。例如:
select *
from (
select dpt_id, sum(salary) as ts,
row_number() over(order by sum(salary)) as rn,
row_number() over(order by sum(salary) desc) as rnd
from t
group by dpt_id
) x
where rn = 1 or rnd = 1
结果:
dpt_id ts rn rnd
------- ----- --- ---
6 500 1 4
5 3100 4 1
参见小提琴。