Как мне получить N результатов для нескольких групп в запрос оракула.
Например, учитывая следующую таблицу:
|--------+------------+------------|
| emp_id | name | occupation |
|--------+------------+------------|
| 1 | John Smith | Accountant |
| 2 | Jane Doe | Engineer |
| 3 | Jack 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 разных сотрудника, работающих по одной профессии. К сожалению, он предоставит вам ВСЕ их комбинации.
Кто-нибудь может сократить это, пожалуйста?
У меня сейчас нет под рукой экземпляра оракула, поэтому я не тестировал это:
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)
просто сделайте ЗАКАЗ в подзапросе в соответствии с вашими потребностями
Это дает то, что вы хотите, и не использует никаких специфичных для поставщика функций 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 вы можете использовать оконные функции, которые предназначены для такого рода запросов.
@ MT0 - Я отредактировал ответ, чтобы решить эти проблемы.
Добавьте RowNum в рейтинг:
select * from
(select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank
from employee)
where rank <= 3
Это НЕТ, дубликат Получить строку, которая имеет максимальное значение для столбца - этот вопрос ищет одну строку на группу, и большинство решений не применимы к этому вопросу, который запрашивает несколько строк на группу.