Jeg tror, at Rank()-funktionen ikke er den rigtige vej med dette, af to grunde.
For det første er den sandsynligvis mindre effektiv end en Min()-baseret metode.
Årsagen til dette er, at forespørgslen skal have en ordnet liste over alle lønninger pr. afdeling, da den scanner dataene, og rangeringen vil så blive tildelt senere ved at genlæse denne liste. I mangel af indekser, der kan udnyttes til dette, kan du naturligvis ikke tildele en rang, før det sidste dataelement er blevet læst, og vedligeholdelse af listen er dyr.
Så ydeevnen af Rank()-funktionen er afhængig af det samlede antal elementer, der skal scannes, og hvis antallet er tilstrækkeligt til, at sorteringen spildes til disken, vil ydeevnen kollapse.
Dette er sandsynligvis mere effektivt:
select dept,
emp,
salary
from
(
SELECT dept,
emp,
salary,
Min(salary) Over (Partition By dept) min_salary
FROM mytable
)
where salary = min_salary
/
Denne metode kræver kun, at forespørgslen opretholder en enkelt værdi pr. afdeling af den minimale værdi, der er fundet indtil videre. Hvis der stødes på et nyt minimum, ændres den eksisterende værdi, ellers kasseres den nye værdi. Det samlede antal elementer, der skal opbevares i hukommelsen, er relateret til antallet af afdelinger, ikke antallet af scannede rækker.
Det kan være, at Oracle har en kodesti til at genkende, at Rank ikke virkelig skal beregnes i dette tilfælde, men jeg ville ikke satse på det.
Den anden grund til at ikke lide Rank() er, at den bare besvarer det forkerte spørgsmål. Spørgsmålet er ikke "Hvilke poster har den løn, der er den første rangering, når lønningerne pr. afdeling er stigende ordnet", det er "Hvilke poster har den løn, der er minimum pr. afdeling". Det gør i hvert fald en stor forskel for mig.