Beholde den nyeste raden per nøkkel
Mønsteret «nyeste post per kunde» med partisjonering etter nøkkel og sortering etter dato.
Beholde den nyeste raden per nøkkel er en gratis leksjon i Forberedelse til kodeintervjuer på CoddyKit. Dette er leksjon 4 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 kodeintervjuer, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Forberedelse til kodeintervjuer inneholder totalt 4 leksjoner.
Spørsmålet om nyeste rad per nøkkel
«Returner den nyeste bestillingen for hver kunde.» «Hent den nyeste statusen for hver enhet.» Dette problemet med nyeste rad per nøkkel er en av de vanligste SQL-oppgavene i intervjuer, fordi det stadig dukker opp i praktisk analysearbeid.
Det er en spesialisert variant av å finne den øverste raden per gruppe: Del inn etter nøkkelen, sorter tidsstempelet synkende, og behold den første raden. Denne leksjonen går grundig gjennom mønsteret og alternativene.
Hvorfor MAX alene ikke er nok
Et fristende første svar er MAX(order_date) gruppert etter kunde. Det gir den nyeste datoen, men ikke resten av raden for den bestillingen, bestillings-ID-en, beløpet eller statusen.
Hvis intervjueren ønsker hele den nyeste raden, trenger MAX sammen med GROUP BY en ekstra join tilbake til tabellen på nøkkelen og den maksimale datoen. Det blir omstendelig og kan gi problemer ved like verdier. Vindusfunksjoner er ryddigere.
-- Gives the date, not the full row
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;Mønsteret med ROW_NUMBER
Del inn etter nøkkelen, sorter tidsstempelet synkende, og den nyeste raden får rn = 1. Behold bare disse radene, så har du hele den nyeste posten per nøkkel.
Dette er standardsvaret. Det returnerer nøyaktig én rad per nøkkel selv når tidsstemplene er like, noe som vanligvis ligger i betydningen av «den nyeste raden».
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC
) AS rn
FROM orders
)
SELECT customer_id, order_id, order_date, amount
FROM ranked
WHERE rn = 1;Bryte likheter i tidsstempler
To bestillinger for samme kunde kan ha samme order_date (samme dag eller identiske tidsstempler). Uten en tie-breaker er det tilfeldig hvilken av dem som blir rn = 1, og resultatet kan endre seg mellom kjøringer.
Legg til en unik sekundærnøkkel, for eksempel order_id DESC, slik at den nyeste raden blir entydig. Intervjuere undersøker spesielt om du legger merke til dette spesialtilfellet.
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC, order_id DESC
) AS rnNyeste rad eller alle like verdier
Avklar hva «nyest» betyr når tidsstemplene er like:
- Hvis du vil ha nøyaktig én rad per nøkkel → bruk
ROW_NUMBERmed en tie-breaker. - Hvis du vil ha alle rader som deler det høyeste tidsstempelet → bruk
RANK() = 1i stedet. Da returneres alle nyeste rader med likt tidsstempel.
Å stille dette oppklarende spørsmålet viser at du forstår betydningen, ikke bare syntaksen.
WITH ranked AS (
SELECT *,
RANK() OVER (
PARTITION BY customer_id ORDER BY order_date DESC
) AS rnk
FROM orders
)
SELECT * FROM ranked WHERE rnk = 1;Alternativet med korrelert underforespørsel
Før vindusfunksjoner ble allment tilgjengelige, brukte man en korrelert underforespørsel for å finne den nyeste raden per nøkkel: Behold en rad bare hvis ingen annen rad for samme nøkkel har en senere dato.
Det fungerer, men den indre spørringen kjøres én gang per rad. Derfor er metoden tregere på store tabeller og upraktisk ved like verdier. Nevn den for å vise spennvidde, men foretrekk vindusfunksjoner av hensyn til ytelsen.
SELECT o.*
FROM orders o
WHERE o.order_date = (
SELECT MAX(o2.order_date)
FROM orders o2
WHERE o2.customer_id = o.customer_id
);DISTINCT ON-kortvariant i Postgres
PostgreSQL tilbyr en kortfattet uttrykksmåte: DISTINCT ON (key) beholder den første raden per nøkkel i henhold til ORDER BY. ORDER BY må begynne med de samme nøkkelkolonnene, etterfulgt av tie-breakeren eller tidsstempelet.
Dette er elegant og raskt i Postgres, men kan ikke porteres mellom databaser. Nevn det som en dialektspesifikk bonus, men behold ROW_NUMBER som standardvalget ditt på tvers av databaser.
SELECT DISTINCT ON (customer_id)
customer_id, order_id, order_date, amount
FROM orders
ORDER BY customer_id, order_date DESC, order_id DESC;Nyeste rad med en betingelse
Praktiske spørsmål legger til filtre: «den nyeste fullførte bestillingen per kunde». Bruk filteret før rangeringen, slik at bare rader som oppfyller betingelsen, blir nummerert.
Plasser betingelsen i WHERE i den indre spørringen (den kjøres før vindusfunksjonen), og bruk deretter rn = 1 i den ytre spørringen. Hvis du filtrerer etter rangeringen, får du feil rad.
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY customer_id ORDER BY order_date DESC, order_id DESC
) AS rn
FROM orders
WHERE status = 'completed'
)
SELECT * FROM ranked WHERE rn = 1;Gjennomgått eksempel: Nyeste enhetsstatus
En status_log-tabell registrerer device_id, status og logged_at. For å hente gjeldende status for hver enhet deler du inn etter device_id, sorterer etter logged_at DESC og beholder rn = 1.
Dette er grunnlaget for oversikter som viser «gjeldende tilstand» for mange enheter fra en hendelseslogg som bare utvides. Den samme oppskriften brukes til spørringer for nyeste pris, nyeste posisjon og nyeste versjon.
WITH latest AS (
SELECT device_id, status, logged_at,
ROW_NUMBER() OVER (
PARTITION BY device_id ORDER BY logged_at DESC
) AS rn
FROM status_log
)
SELECT device_id, status, logged_at
FROM latest
WHERE rn = 1;Ytelsesmerknader
Poenger som gir uttelling på seniornivå:
- En indeks på
(customer_id, order_date DESC)gjør at motoren effektivt kan lese den nyeste raden per nøkkel. - Vindustilnærmingen skanner tabellen én gang, mens den korrelerte underforespørselen ikke gjør det.
DISTINCT ONi Postgres kan bruke den samme indeksen og er ofte det raskeste alternativet for én tabell.- For hendelseslogger med mange nye poster bør du vurdere en materialisert «nyeste»-tabell som oppdateres trinnvis.
Vanlige feil
Vær oppmerksom på følgende:
- Å bruke
MAX(date)og bare returnere datoen, ikke hele raden. - Å glemme tie-breakeren, slik at resultatene blir ikke-deterministiske når datoene er like.
- Å filtrere på betingelsen etter rangeringen, slik at en rad som skulle vært utelatt, kan bli valgt.
- Å forveksle «nyeste ene rad» (
ROW_NUMBER) med «alle nyeste rader med lik verdi» (RANK).
Hurtigsjekk
Velg riktig spørring for nyeste rad per nøkkel.
Oppsummering: Nyeste rad per nøkkel
Mønsteret er: PARTITION BY key, ORDER BY timestamp DESC (pluss en unik tie-breaker), behold rn = 1.
MAX(date)gir datoen, ikke hele raden.- Legg alltid til en tie-breaker for å få et entydig resultat.
- Bruk
RANK() = 1hvis du vil ha alle rader med samme nyeste tidsstempel. - Filterbetingelser hører hjemme i den indre spørringen, før rangeringen.
- Postgres
DISTINCT ONer et kortfattet og raskt, dialektspesifikt alternativ.
Lær deg Forberedelse til kodeintervjuer 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
- 90
- Leksjoner
- 360
Ofte stilte spørsmål
Er leksjonen «Beholde den nyeste raden per nøkkel» gratis?
Ja – hele teksten i «Beholde den nyeste raden per nøkkel» 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 kodeintervjuer-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Forberedelse til kodeintervjuer inneholder totalt 4 leksjoner.
Hva lærer jeg i «Beholde den nyeste raden per nøkkel»?
Mønsteret «nyeste post per kunde» med partisjonering etter nøkkel og sortering etter dato. Du øver på Forberedelse til kodeintervjuer 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 kodeintervjuer?
Ingen tidligere erfaring er nødvendig. Forberedelse til kodeintervjuer 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 4 av 4.
Hvor lang tid tar leksjonen «Beholde den nyeste raden per nøkkel»?
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 kodeintervjuer-leksjonen?
Ja. Alle Forberedelse til kodeintervjuer-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
- De N øverste radene per gruppe med ROW_NUMBER
- Håndtere like resultater i topp-N
- Fjerne duplikate rader på en trygg måte
- Beholde den nyeste raden per nøkkel