16

我如何能够在 oracle 查询中为多个组获得 N 个结果。

例如,给定下表:

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

有更多的行有更多的职业。我想从每个职业中获得三名员工(比如说)。

有没有办法在不使用子查询的情况下做到这一点?

4

5 回答 5

41

我现在没有方便的 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

于 2008-09-25T18:27:48.760 回答
14

这会产生您想要的东西,并且它不使用特定于供应商的 SQL 功能,例如 TOP N 或 RANK()。

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

在此示例中,它为每个职业的 emp_id 值最低的三名员工提供了信息。您可以更改不平等比较中使用的属性,使其按姓名或其他方式提供顶级员工。

于 2008-09-25T20:48:29.903 回答
3

将 RowNum 添加到排名:

select * from 
         (select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank   
                      from employee) 
         where rank <= 3 
于 2011-06-07T10:05:12.793 回答
1

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

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 名不同员工的行,这些员工都在同一职业中。不幸的是,它会给你这些的所有组合。

请问有人能把这个减掉吗?

于 2008-09-25T18:24:55.007 回答
1

在 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 即可满足您的需求

于 2008-09-25T18:32:12.150 回答