Den best betalte i hver avdeling
Kombiner partisjonering med rangering for grupperte topp-N-problemer med lønn.
Den best betalte i hver avdeling er en gratis leksjon i Forberedelse til SQL-intervju på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Forberedelse til SQL-intervju, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Forberedelse til SQL-intervju inneholder totalt 4 leksjoner.
Fra global rangering til rangering per gruppe
Den neste utfordringen er: «Finn den best betalte ansatte i hver avdeling.» Dette kombinerer rangering med gruppering og er et typisk spørsmål på mellomnivå.
Anta en employee-tabell med id, name, department_id og salary. Vi ønsker én eller flere av de best betalte per avdeling ved like verdier, ikke bare den globale maksimumsverdien.
Det viktigste nye verktøyet er PARTITION BY, som starter rangeringen på nytt i hver avdeling.
CREATE TABLE employee (
id INT PRIMARY KEY,
name VARCHAR(100),
department_id INT,
salary INT
);PARTITION BY starter rangeringen på nytt
Når De legger til PARTITION BY department_id i vinduet, ber De databasen beregne rangeringen uavhengig innenfor hver avdeling.
Hver avdeling starter med sin egen rang 1. Den best betalte ansatte i avdeling 1 og den best betalte ansatte i avdeling 5 får derfor begge rang 1. Uten partisjonering ville bare den ene globale maksimumsverdien fått rang 1.
SELECT name, department_id, salary,
DENSE_RANK() OVER (
PARTITION BY department_id
ORDER BY salary DESC
) AS rnk
FROM employee;Filtrering til rang 1
For å beholde bare de best betalte ansatte pakker De inn den rangerte spørringen og filtrerer etter rang 1. Som alltid må vindusfunksjonen beregnes i en underspørring eller CTE før De kan filtrere på den.
Ved å bruke DENSE_RANK (eller RANK) her får De med begge ansatte hvis to ansatte har samme høyeste lønn i en avdeling. Det er vanligvis den riktige tolkningen av «den best betalte ansatte».
SELECT name, department_id, salary
FROM (
SELECT name, department_id, salary,
DENSE_RANK() OVER (
PARTITION BY department_id
ORDER BY salary DESC
) AS rnk
FROM employee
) t
WHERE rnk = 1;ROW_NUMBER når du vil ha nøyaktig én
Noen ganger vil intervjueren ha nøyaktig én rad per avdeling, selv om det er likhet i resultatet. Da bruker du ROW_NUMBER og legger til en deterministisk tie-breaker, for eksempel den laveste id-en.
Uten tie-breakeren avgjøres like resultater vilkårlig, og resultatet blir ikke-deterministisk. Når du legger til , id ASC, blir valget reproduserbart.
SELECT name, department_id, salary
FROM (
SELECT name, department_id, salary,
ROW_NUMBER() OVER (
PARTITION BY department_id
ORDER BY salary DESC, id ASC
) AS rn
FROM employee
) t
WHERE rn = 1;DENSE_RANK kontra ROW_NUMBER kontra RANK her
Velg basert på den nøyaktige ordlyden:
- DENSE_RANK = 1: alle ansatte som deler den høyeste lønnen i hver avdeling.
- RANK = 1: identisk med DENSE_RANK for den høyeste rangeringen (hopp i rangeringen har bare betydning under rang 1).
- ROW_NUMBER = 1: nøyaktig én ansatt per avdeling, med tie-breakeren angitt i ORDER BY.
Det er dette intervjuere vurderer: om du sier hvilken du valgte, og hvorfor.
Den korrelerte tilnærmingen før vindusfunksjoner
Før vindusfunksjoner var standardløsningen en korrelert underspørring: Behold en rad bare hvis ingen i samme avdeling tjener mer.
Dette returnerer naturlig alle som deler topplassen. Løsningen er portabel, men kan være treg fordi den indre MAX-beregningen utføres for hver ytre rad, med mindre optimalisereren omskriver den.
SELECT e.name, e.department_id, e.salary
FROM employee e
WHERE e.salary = (
SELECT MAX(e2.salary)
FROM employee e2
WHERE e2.department_id = e.department_id
);Tilnærmingen med GROUP BY og JOIN
Et annet portabelt mønster er å beregne den høyeste lønnen per avdeling med GROUP BY og deretter koble resultatet tilbake for å hente de ansatte som matcher.
Dette er effektivt og tydelig. Koblingen henter tilbake alle ansatte hvis lønn er lik den høyeste lønnen i avdelingen, så like resultater bevares.
SELECT e.name, e.department_id, e.salary
FROM employee e
JOIN (
SELECT department_id, MAX(salary) AS max_sal
FROM employee
GROUP BY department_id
) m
ON e.department_id = m.department_id
AND e.salary = m.max_sal;Topp N per avdeling
Mønsteret kan utvides til «de tre best betalte per avdeling» uten noen nye ideer. Bare endre filteret til et intervall.
Med DENSE_RANK returnerer rnk <= 3 de tre høyeste ulike lønnsnivåene (muligens flere enn tre rader ved lik lønn). Med ROW_NUMBER returnerer rn <= 3 nøyaktig tre rader per avdeling.
SELECT name, department_id, salary
FROM (
SELECT name, department_id, salary,
DENSE_RANK() OVER (
PARTITION BY department_id
ORDER BY salary DESC
) AS rnk
FROM employee
) t
WHERE rnk <= 3;Gjennomgått eksempel
Avdeling 1: Ana 120, Bob 120, Cara 90. Avdeling 2: Dan 200, Eve 150.
- DENSE_RANK = 1: Ana (120) og Bob (120) fra avdeling 1, samt Dan (200) fra avdeling 2. Tre rader.
- ROW_NUMBER = 1 med id som tie-breaker: én av Ana og Bob (den som har lavest id), samt Dan. To rader.
De samme dataene kan gi ulikt antall rader avhengig av funksjonen. Velg den som passer til spørsmålet.
Ta med avdelinger og koble inn navn
Intervjuere legger ofte til en department-tabell og ber om avdelingsnavnet. Bare koble den inn etter rangeringen.
Behold rangeringen på employee-tabellen og koble oppslagstabellen til slutt, slik at partisjoneringen fortsatt skjer på riktig granularitetsnivå.
SELECT d.name AS department, t.name AS employee, t.salary
FROM (
SELECT name, department_id, salary,
DENSE_RANK() OVER (
PARTITION BY department_id ORDER BY salary DESC
) AS rnk
FROM employee
) t
JOIN department d ON d.id = t.department_id
WHERE t.rnk = 1;Fallgruver du bør unngå
Vanlige feil ved rangering per gruppe:
- Å glemme
PARTITION BYog rangere globalt, slik at bare den best betalte ansatte i hele selskapet returneres. - Å bruke
ROW_NUMBERnår spørsmålet antyder at alle med lik topplassering skal vises, slik at noen av de best betalte ansatte forsvinner uten varsel. - Å forsøke å plassere vindusfunksjonen direkte i
WHEREi stedet for å pakke den inn. - Å koble inn avdelingstabellen før rangeringen og dermed utilsiktet endre partisjoneringens granularitet.
Hurtigsjekk
Velg riktig rangeringsfunksjon for kravet.
Oppsummering
Den best betalte per avdeling følger det globale rangeringsmønsteret, pluss PARTITION BY department_id:
- DENSE_RANK = 1 returnerer alle ansatte som deler topplassen i hver avdeling.
- ROW_NUMBER = 1 med en tie-breaker returnerer nøyaktig én per avdeling.
- Portable alternativer er korrelert
MAXper avdeling eller maksimum beregnet medGROUP BYog koblet tilbake til tabellen.
Utvid til topp-N ved å endre = 1 til <= N. Si tydelig hvilken håndtering av like resultater du har valgt.
Lær deg SQL med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Den best betalte i hver avdeling» gratis?
Ja – hele teksten i «Den best betalte i hver avdeling» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Forberedelse til SQL-intervju-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Forberedelse til SQL-intervju inneholder totalt 4 leksjoner.
Hva lærer jeg i «Den best betalte i hver avdeling»?
Kombiner partisjonering med rangering for grupperte topp-N-problemer med lønn. Du øver på Forberedelse til SQL-intervju med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Forberedelse til SQL-intervju?
Ingen tidligere erfaring er nødvendig. Forberedelse til SQL-intervju på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Den best betalte i hver avdeling»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Forberedelse til SQL-intervju-leksjonen?
Ja. Alle Forberedelse til SQL-intervju-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Nest høyeste lønn – fem metoder
- Den n-te høyeste verdien med DENSE_RANK
- Den best betalte i hver avdeling
- Returnere NULL når den n-te verdien ikke finnes