Question

Je suis nouveau à travailler avec des fonctions analytiques.

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  10 JOHN  200000
  10 SCOTT 300000
  20 BOB   100000
  20 BETTY 200000
  30 ALAN  100000
  30 TOM   200000
  30 JEFF  300000

Je veux que le département et l'employé avec un salaire minimum.

Les résultats devraient ressembler à:

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  20 BOB   100000
  30 ALAN  100000

EDIT: Voici le SQL je (mais bien sûr, cela ne fonctionne pas comme il veut le personnel du groupe par article, ainsi):

SELECT dept, 
  emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary)
FROM mytable
GROUP BY dept
Était-ce utile?

La solution

Je pense que la fonction Rank () n'est pas la voie à suivre ce, pour deux raisons.

Tout d'abord, il est sans doute moins efficace qu'un min () -. Méthode basée sur

La raison est que la requête doit maintenir une liste ordonnée de tous les salaires par département car il analyse les données et le rang sera alors attribué plus tard en relisant cette liste. De toute évidence, en l'absence d'indices qui peuvent être mises à profit pour cela, vous ne pouvez pas attribuer un rang jusqu'à ce que le dernier élément de données a été lu, et le maintien de la liste est cher.

Ainsi, la performance de la fonction Rank () dépend du nombre total d'éléments à analyser, et si le nombre est suffisant que les déversements de tri sur le disque puis la performance s'effondrer.

Ceci est probablement plus efficace:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

Cette méthode exige seulement que la requête à maintenir une valeur unique par département de la valeur minimum rencontrée jusqu'à présent. Si un nouveau minimum est détectée alors la valeur existante est modifiée, sinon la nouvelle valeur est mis au rebut. Le nombre total d'éléments qui doivent être conservées en mémoire est liée au nombre de services, et non pas le nombre de lignes balayées.

Il se pourrait que Oracle a un chemin de code pour reconnaître que le rang n'a pas vraiment besoin d'être calculé dans ce cas, mais je ne parierais pas là-dessus.

La deuxième raison de ne pas aimer Rang () est qu'il répond simplement à la mauvaise question. La question est pas des « documents qui ont le salaire qui est le premier rang lorsque les salaires par département sont commandés par ordre croissant », il est « dossiers qui ont le salaire qui est le minimum par département ». Cela fait une grande différence pour moi, au moins.

Autres conseils

Je pense que vous étiez assez proche avec votre demande originale. Ce qui suit ruisselait et faire correspondre votre cas de test:

SELECT dept, 
  MIN(emp) KEEP(DENSE_RANK FIRST ORDER BY salary, ROWID) AS emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary, ROWID) AS salary
FROM mytable
GROUP BY dept

Contrairement aux solutions RANK (), celui-ci garantit au plus une ligne par département. Mais cela fait allusion à un problème: ce qui se passe dans un département où il y a deux employés sur le salaire le plus bas? Les solutions RANK () retournera les deux employés - plus d'une ligne pour le département. Cette réponse choisira une manière arbitraire et assurez-vous qu'il n'y a qu'un seul pour le département.

Vous pouvez utiliser la syntaxe RANK(). Par exemple, cette requête vous dira où un employé se classe au sein de leur département en ce qui concerne la taille de leur salaire est:

SELECT
  dept,
  emp,
  salary,
  (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
FROM EMPLOYEES

Vous pouvez ensuite interroger à partir de ce où salary_rank_within_dept = 1:

SELECT * FROM
  (
    SELECT
      dept,
      emp,
      salary,
      (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
    FROM EMPLOYEES
  )
WHERE salary_rank_within_dept = 1
select e2.dept, e2.emp, e2.salary
from employee e2
where e2.salary = (select min(e1.salary) from employee e1)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top