获得每个组的最佳结果(在Oracle中)

时间:2020-03-06 14:44:20  来源:igfitidea点击:

我如何才能获得N个针对几个小组的结果
一个oracle查询。

例如,给定下表:

|--------+------------+------------|
| emp_id | name       | occupation |
|--------+------------+------------|
|      1 | John Smith | Accountant |
|      2 | Jane Doe   | Engineer   |
|      3 | Hyman Black | Funnyman   |
|--------+------------+------------|

有更多行和更多职业。我想得到
每个职业有三名员工(可以说)。

有没有不使用子查询来执行此操作的方法?

解决方案

我不确定这是否非常有效,但也许是一个起点?

select *
from people p1
    join people p2
        on p1.occupation = p2.occupation
    join people p3
        on p1.occupation = p3.occupation
        and p2.occupation = p3.occupation
where p1.emp_id != p2.emp_id
    and p1.emp_id != p3.emp_id

这应该为我们提供包含3个不同雇员的行,这些雇员全部处于同一职业。不幸的是,它将为我们提供所有这些组合。

任何人都可以减少这个吗?

我现在没有手头的oracle实例,因此我没有对此进行测试:

select *
from (select emp_id, name, occupation,
      rank() over ( partition by occupation order by emp_id) rank
      from employee)
where rank <= 3

这是有关排名如何工作的链接:http://www.psoug.org/reference/rank.html

在SQL Server中对此进行了测试(它使用了子查询)

select emp_id, name, occupation
from employees t1
where emp_id IN (select top 3 emp_id from employees t2 where t2.occupation = t1.occupation)

只需在子查询中执行ORDER by即可满足需求

这将产生所需的内容,并且不使用供应商特定的SQL功能(例如TOP N或者RANK())。

SELECT e.name, e.occupation 
FROM emp AS e 
  LEFT OUTER JOIN emp AS e2 
    ON (e.occupation = e2.occupation AND e.emp_id <= e2.emp_id) 
GROUP BY e.emp_id 
HAVING COUNT(*) <= 3 
ORDER BY e.occupation;

在此示例中,它为三名雇员提供每个职业emp_id最低的值。我们可以更改不等式比较中使用的属性,以使其按名称或者其他方式赋予高层雇员。