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

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

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

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

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

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

Это НЕТ, дубликат Получить строку, которая имеет максимальное значение для столбца - этот вопрос ищет одну строку на группу, и большинство решений не применимы к этому вопросу, который запрашивает несколько строк на группу.

MT0 26.09.2018 12:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
16
1
70 948
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

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

У меня сейчас нет под рукой экземпляра оракула, поэтому я не тестировал это:

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

Без подзапроса не указали ...?

AviD 25.09.2008 23:26

Да, но он вполне мог иметь в виду «без использования подзапроса, который снова выбирает из той же таблицы». Это решение использует подзапрос, но обращается к таблице только один раз.

Tony Andrews 26.09.2008 14:32

Отлично работает, похоже, тоже опирается на БД.

cody.tv.weber 20.03.2018 20:58

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

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

Ответ принят как подходящий

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

@ codemon2002, используйте ответ, опубликованный jop в этой теме. В Oracle вы можете использовать оконные функции, которые предназначены для такого рода запросов.

Bill Karwin 20.03.2018 20:50

@ MT0 - Я отредактировал ответ, чтобы решить эти проблемы.

Bill Karwin 26.09.2018 17:21

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

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

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