如何从没有UNION,INTERSECT等的有序查询中选择第一个和最后一个记录

时间:2016-03-16 18:38:08

标签: sql oracle group-by sql-order-by union

所以,我承认这是我昨天的考试任务之一,但我没有处理它...... 我有一个简单的人员数据库,他们的名字,工资和功能(A,B,C,D,E和F),我必须选择具有最高和最低平均工资的职能。我还要忽略功能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

我知道如何使用UNION进行操作,因为在oracle中我可以通过按工资顺序按工资分组,按工资desc按顺序组合,例如只在两个选择中获取1行。我可以使用WHERE但是不可能将WHERE与聚合一起使用(如AVG(薪水)),但如何在没有UNION,MINUS或INTERSECT的单一查询中进行操作?

4 个答案:

答案 0 :(得分:2)

您可以使用calloc函数(如果平均值可以使用rank),则可以按平均工资对行进行排序。然后选择排名最高和排名最低的行。

dense_rank

答案 1 :(得分:2)

与@ vkp的方法类似,但没有连接回基表:

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()调用按顺序放置每个函数/平均值:

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()打破关系来避免这种情况。

答案 2 :(得分:1)

如果你想要返回一个最小/最大行,你可能会在避免两个不同的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将失败。

答案 3 :(得分:0)

您可以在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)