如何在没有 UNION、INTERSECT 等的情况下 select 有序查询中的第一条和最后一条记录
How to select first and last record from ordered query without UNION, INTERSECT etc
所以,我承认这是我昨天的考试任务之一,我没有处理好...
我有一个简单的人员数据库,包含他们的姓名、薪水和职能(A、B、C、D、E 和 F),我必须 select 具有最高和最低平均薪水的职能。我还不得不忽略函数 C。
数据库示例:
name salary function
Mike 100 A
John 200 F
Jenny 500 B
Fred 400 B
... 250 C
... 800 D
... 100 E
... 350 E
... 450 F
... 250 A
... 500 B
结果示例:
function avg salary
A 300
C 600
我知道如何像在 oracle 中一样使用 UNION 来做到这一点,我可以按工资顺序按函数分组,按工资 desc 顺序合并,例如只在两个 select 中获取 1 行。我本可以使用 WHERE,但不可能将 WHERE 与聚合一起使用(如 AVG(salary)),但是如何在没有 UNION、MINUS 或 INTERSECT 的情况下在单个查询中执行此操作?
您可以使用 rank
函数(如果平均值可能有联系,则使用 dense_rank
)按平均工资对行进行排序。然后 select 排名最高和最低的行。
select t1.function, avg(t1.salary)
from (select
rank() over(order by avg(salary) desc) rnk_high
,rank() over(order by avg(salary)) rnk_low
,function
from tablename
group by function) t
join tablename t1 on t.function = t1.function
where rnk_high = 1 or rnk_low = 1
group by t1.function
你能在 Oracle 中使用子查询吗?
试试这个
Select z.Function from
(Select Function, Avg(Salary) avgSal
from tableName
group By function) z
Where z.avgSal = (Select Max(z0.avgSal)
from (Select Avg(Salary) avgSal
from tableName
group By function) z0)
Or z.avgSal = (Select Min(z1.avgSal)
from (Select Avg(Salary) avgSal
from tableName
group By function) z1)
类似于@vkp 的方法,但没有连接回基 table:
select function, avg_salary
from (
select function, avg(salary) as avg_salary,
rank() over (order by avg(salary)) as rnk_asc,
rank() over (order by avg(salary) desc) as rnk_desc
from tablename
group by function
)
where rnk_asc = 1 or rnk_desc = 1;
F AVG_SALARY
- ----------
D 800
A 175
两个 rank()
调用将每个 function/average 排序:
select function, avg(salary) as avg_salary,
rank() over (order by avg(salary)) as rnk_asc,
rank() over (order by avg(salary) desc) as rnk_desc
from tablename
group by function;
F AVG_SALARY RNK_ASC RNK_DESC
- ---------- ---------- ----------
D 800 6 1
B 4.7E+02 5 2
F 325 4 3
C 250 3 4
E 225 2 5
A 175 1 6
即形成内联视图;外部查询然后只选择在生成的列中排名第 1 的行,这里是 D 和 A。
如果您有两个具有相同平均工资的职能,那么他们将获得相同的排名,并且都排名为 1,那么您会看到两者;所以你可以获得两个以上的结果。那可能就是你想要的。如果不是,您可以通过使用 rank()
或 dense_rank()
.
定义如何打破关系来避免它
如果你想 return 正好是一个 min/max 行,当你避免两个不同的 ORDER BY:
select function, avg_salary
from (
select function, avg(salary) as avg_salary,
ROW_NUMBER() over (order by avg(salary)) as rnk_asc,
COUNT(*) over () as cnt
from tablename
group by function
)
where rnk_asc = 1 or rnk_asc = cnt;
注意,如果有两行具有相同的 MAX 值(没有行 rnk_asc = cnt
),RANK 将失败。
所以,我承认这是我昨天的考试任务之一,我没有处理好... 我有一个简单的人员数据库,包含他们的姓名、薪水和职能(A、B、C、D、E 和 F),我必须 select 具有最高和最低平均薪水的职能。我还不得不忽略函数 C。 数据库示例:
name salary function
Mike 100 A
John 200 F
Jenny 500 B
Fred 400 B
... 250 C
... 800 D
... 100 E
... 350 E
... 450 F
... 250 A
... 500 B
结果示例:
function avg salary
A 300
C 600
我知道如何像在 oracle 中一样使用 UNION 来做到这一点,我可以按工资顺序按函数分组,按工资 desc 顺序合并,例如只在两个 select 中获取 1 行。我本可以使用 WHERE,但不可能将 WHERE 与聚合一起使用(如 AVG(salary)),但是如何在没有 UNION、MINUS 或 INTERSECT 的情况下在单个查询中执行此操作?
您可以使用 rank
函数(如果平均值可能有联系,则使用 dense_rank
)按平均工资对行进行排序。然后 select 排名最高和最低的行。
select t1.function, avg(t1.salary)
from (select
rank() over(order by avg(salary) desc) rnk_high
,rank() over(order by avg(salary)) rnk_low
,function
from tablename
group by function) t
join tablename t1 on t.function = t1.function
where rnk_high = 1 or rnk_low = 1
group by t1.function
你能在 Oracle 中使用子查询吗? 试试这个
Select z.Function from
(Select Function, Avg(Salary) avgSal
from tableName
group By function) z
Where z.avgSal = (Select Max(z0.avgSal)
from (Select Avg(Salary) avgSal
from tableName
group By function) z0)
Or z.avgSal = (Select Min(z1.avgSal)
from (Select Avg(Salary) avgSal
from tableName
group By function) z1)
类似于@vkp 的方法,但没有连接回基 table:
select function, avg_salary
from (
select function, avg(salary) as avg_salary,
rank() over (order by avg(salary)) as rnk_asc,
rank() over (order by avg(salary) desc) as rnk_desc
from tablename
group by function
)
where rnk_asc = 1 or rnk_desc = 1;
F AVG_SALARY
- ----------
D 800
A 175
两个 rank()
调用将每个 function/average 排序:
select function, avg(salary) as avg_salary,
rank() over (order by avg(salary)) as rnk_asc,
rank() over (order by avg(salary) desc) as rnk_desc
from tablename
group by function;
F AVG_SALARY RNK_ASC RNK_DESC
- ---------- ---------- ----------
D 800 6 1
B 4.7E+02 5 2
F 325 4 3
C 250 3 4
E 225 2 5
A 175 1 6
即形成内联视图;外部查询然后只选择在生成的列中排名第 1 的行,这里是 D 和 A。
如果您有两个具有相同平均工资的职能,那么他们将获得相同的排名,并且都排名为 1,那么您会看到两者;所以你可以获得两个以上的结果。那可能就是你想要的。如果不是,您可以通过使用 rank()
或 dense_rank()
.
如果你想 return 正好是一个 min/max 行,当你避免两个不同的 ORDER BY:
select function, avg_salary
from (
select function, avg(salary) as avg_salary,
ROW_NUMBER() over (order by avg(salary)) as rnk_asc,
COUNT(*) over () as cnt
from tablename
group by function
)
where rnk_asc = 1 or rnk_asc = cnt;
注意,如果有两行具有相同的 MAX 值(没有行 rnk_asc = cnt
),RANK 将失败。