Получить лучшие результаты для каждой группы (в Oracle) - PullRequest
11 голосов
/ 25 сентября 2008

Как бы я мог получить N результатов для нескольких групп в запрос оракула. ​​

Например, с учетом следующей таблицы:

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

Есть еще много строк с большим количеством профессий. Я хотел бы получить три сотрудника (скажем так) от каждого занятия.

Есть ли способ сделать это без использования подзапроса?

Ответы [ 5 ]

34 голосов
/ 25 сентября 2008

У меня сейчас нет экземпляра 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

11 голосов
/ 26 сентября 2008

Это производит то, что вы хотите, и не использует специфичные для поставщика функции 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 на занятие. Вы можете изменить атрибут, используемый при сравнении неравенств, чтобы он давал топ-сотрудникам имена или что-то еще.

3 голосов
/ 07 июня 2011

Добавить RowNum в ранг:

select * from 
         (select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank   
                      from employee) 
         where rank <= 3 
1 голос
/ 25 сентября 2008

проверил это в 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)

просто ЗАКАЗАТЬ в подзапросе, чтобы удовлетворить ваши потребности

1 голос
/ 25 сентября 2008

Я не уверен, что это очень эффективно, но, может быть, стартовое место?

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 разных сотрудника, все в одной профессии. К сожалению, это даст вам ВСЕ комбинации из них.

Может кто-нибудь сократить это, пожалуйста?

...