Obtenez les meilleurs résultats pour chaque groupe (dans Oracle)
-
02-07-2019 - |
Question
Comment pourrais-je obtenir N résultats pour plusieurs groupes dans une requête oracle.
Par exemple, à l'aide du tableau suivant:
|--------+------------+------------|
| emp_id | name | occupation |
|--------+------------+------------|
| 1 | John Smith | Accountant |
| 2 | Jane Doe | Engineer |
| 3 | Jack Black | Funnyman |
|--------+------------+------------|
Il y a beaucoup plus de lignes avec plus de professions. Je voudrais obtenir trois employés (disons) de chaque profession.
Y a-t-il un moyen de faire cela sans utiliser de sous-requête?
La solution
Ceci produit ce que vous voulez et n’utilise aucune fonctionnalité SQL spécifique au fournisseur, telle que 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;
Dans cet exemple, il donne les trois employés avec les valeurs d'emp_id les plus basses par profession. Vous pouvez modifier l’attribut utilisé dans la comparaison d’inégalités pour que les meilleurs employés soient nommés, ou autre chose.
Autres conseils
Je n'ai pas d'instance Oracle à portée de main pour le moment, donc je n'ai pas testé ceci:
select *
from (select emp_id, name, occupation,
rank() over ( partition by occupation order by emp_id) rank
from employee)
where rank <= 3
Voici un lien sur le fonctionnement du classement: http://www.psoug.org/reference /rank.html
Ajouter RowNum au classement:
select * from
(select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank
from employee)
where rank <= 3
a testé cela dans SQL Server (et utilise une sous-requête)
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)
il suffit de faire une commande par dans la sous-requête pour répondre à vos besoins
Je ne suis pas sûr que cela soit très efficace, mais peut-être un point de départ?
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
Cela devrait vous donner des lignes contenant 3 employés distincts, tous dans le même métier. Malheureusement, cela vous donnera TOUTES les combinaisons.
Quelqu'un peut-il réduire cela s'il vous plaît?