如何在没有 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 将失败。