Obter os melhores resultados para cada grupo (em Oracle)
-
02-07-2019 - |
Pergunta
Como eu poderia ser capaz de obter resultados N por vários grupos na uma consulta Oracle.
Por exemplo, dada a tabela a seguir:
|--------+------------+------------|
| emp_id | name | occupation |
|--------+------------+------------|
| 1 | John Smith | Accountant |
| 2 | Jane Doe | Engineer |
| 3 | Jack Black | Funnyman |
|--------+------------+------------|
Existem muitas linhas mais com mais ocupações. Eu gostaria de obter três funcionários (digamos) de cada ocupação.
Existe uma maneira de fazer isso sem usar uma subconsulta?
Solução
Isso produz o que você quer, e não utiliza recursos do SQL específicos do fornecedor como TOP N ou 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;
Neste exemplo, ele dá os três funcionários com os valores mais baixos emp_id por ocupação. Você pode alterar o atributo usado na comparação de desigualdade, para torná-lo dar os principais funcionários pelo nome, ou o que quer.
Outras dicas
Eu não tenho uma instância Oracle calhar agora, então eu não testei isso:
select *
from (select emp_id, name, occupation,
rank() over ( partition by occupation order by emp_id) rank
from employee)
where rank <= 3
Aqui está um link sobre como funciona Rank: http://www.psoug.org/reference /rank.html
Adicionar rowNum a classificação:
select * from
(select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank
from employee)
where rank <= 3
testado isso em SQL Server (e usa subconsulta)
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)
apenas fazer um ORDER BY na subconsulta para atender às suas necessidades
Eu não estou certo de que este é muito eficiente, mas talvez um ponto de partida?
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
Isso deve lhe dar linhas que contêm 3 funcionários distintos tudo na mesma profissão. Infelizmente, ele vai te dar todas as combinações desses.
Pode alguém pare este para baixo por favor?