Получите лучшие результаты для каждой группы (в Oracle)

StackOverflow https://stackoverflow.com/questions/134958

Вопрос

Как я смогу получить n результатов для нескольких групп в Oracle запрос.

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

просто сделайте ЗАКАЗ в подзапросе в соответствии с вашими потребностями

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

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

Это должно дать вам строки, содержащие трех разных сотрудников одной профессии.К сожалению, он даст вам ВСЕ их комбинации.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top