Forberedelse til kodeintervjuer · leksjon

Skrive om korrelerte underspørringer til joiner

Gjør korrelert logikk om til joiner eller window-funksjoner for bedre ytelse.

Leksjon 4 av 413 trinn

Skrive om korrelerte underspørringer til joiner 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.

Hvorfor skrive om i det hele tatt

Korrelert underspørringer er lesbare, men kan være trege: den indre spørringen kan kjøres én gang per ytre rad. Intervjuere ber ofte om at De skal skrive den om til en join eller en vindusfunksjon for å forbedre ytelsen.

Målet er å få det samme resultatet med én gjennomgang av dataene i stedet for gjentatte skanninger av den indre spørringen.

Å kjenne to eller tre mønstre for omskriving, og vite når hvert av dem bevarer korrektheten, er en sentral ferdighet på mellomnivå.

Mønster 1: EXISTS til INNER JOIN

En korrelert EXISTS som tester om det finnes minst ett treff, kan ofte skrives om til en INNER JOIN.

Vær imidlertid oppmerksom på at en join kan produsere dupliserte ytre rader hvis flere indre rader samsvarer. Legg til DISTINCT eller bruk aggregering for å gjenopprette én rad per ytre nøkkel.

-- Correlated EXISTS
SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o
             WHERE o.customer_id = c.customer_id);

-- Join rewrite (DISTINCT avoids dupes from fan-out)
SELECT DISTINCT c.customer_id, c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id;

Fellen med radmangedobling

Den vanligste feilen ved omskriving er å glemme radmangedobling. EXISTS returnerer hver kunde én gang, uansett hvor mange ordrer kunden har. En naiv join returnerer én rad per ordre og blåser opp opptellingene.

Hvis et senere trinn bruker COUNT(*) eller SUM(amount) på det joinede resultatet uten å gruppere nøye, blir tallene feil.

Spør alltid: Kan joinen mangedoble rader? Hvis ja, bruker De DISTINCT eller en GROUP BY for å samle resultatet tilbake.

Mønster 2: NOT EXISTS til LEFT JOIN / IS NULL

Omskriving til anti-join er et sikkert intervjumønster. En korrelert NOT EXISTS blir til en LEFT JOIN der høyresiden er NULL.

Ytre rader uten treff får NULL-verdier på høyresiden. Ved å filtrere på denne NULL-verdien beholder De nøyaktig radene uten treff.

-- Correlated NOT EXISTS
SELECT c.customer_id FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o
                  WHERE o.customer_id = c.customer_id);

-- LEFT JOIN / IS NULL rewrite
SELECT c.customer_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.customer_id IS NULL;

Velg en kolonne som ikke kan være NULL

Ved omskrivingen LEFT JOIN / IS NULL må De teste en kolonne på høyresiden som aldri er NULL ved et reelt treff, helst join-nøkkelen eller primærnøkkelen.

Hvis De tester en kolonne som kan være NULL, kan De ikke skille et ekte manglende treff (ingen rad) fra en rad som faktisk ble funnet, men som har NULL i denne kolonnen. Denne feilen returnerer feil rader.

Bruk av join-nøkkelen (her o.customer_id) eller o.order_id garanterer at NULL betyr "ingen samsvarende rad."

Mønster 3: Skalar aggregering til JOIN + GROUP BY

En korrelert aggregering i SELECT kan bli til en join mot en gruppert underspørring (en avledet tabell).

Beregn aggregeringen per gruppe én gang, og join den deretter tilbake til detaljradene. Den indre spørringen kjøres én gang i stedet for én gang per rad.

-- Correlated scalar aggregate
SELECT e1.name,
       (SELECT MAX(e2.salary) FROM employees e2
        WHERE e2.dept_id = e1.dept_id) AS dept_max
FROM employees e1;

-- Join + GROUP BY rewrite
SELECT e.name, m.dept_max
FROM employees e
JOIN (SELECT dept_id, MAX(salary) AS dept_max
      FROM employees GROUP BY dept_id) m
  ON m.dept_id = e.dept_id;

Mønster 4: Omskriving med vindusfunksjon

Ofte er en vindusfunksjon den ryddigste omskrivingen. MAX(salary) OVER (PARTITION BY dept_id) erstatter den korrelerte aggregeringen fullstendig, uten behov for en join.

Den beregner gruppeverdien i én gjennomgang og beholder alle detaljradene. Dette er vanligvis svaret intervjuere helst vil se for analyseforespørsler.

SELECT name,
       dept_id,
       salary,
       MAX(salary) OVER (PARTITION BY dept_id) AS dept_max
FROM employees;

Omskriving av største-N-per-gruppe

En korrelert underspørring som velger den øverste raden per gruppe (salary = MAX per dept) kan enkelt skrives om med ROW_NUMBER.

Partisjoner etter gruppen, sorter etter måltallet, og behold rangering 1. Bruk RANK i stedet hvis De vil ha med alle øverste rader med samme verdi.

SELECT name, dept_id, salary
FROM (
    SELECT name, dept_id, salary,
           ROW_NUMBER() OVER (PARTITION BY dept_id
                              ORDER BY salary DESC) AS rn
    FROM employees
) t
WHERE rn = 1;

Når De ikke bør skrive om

Omskriving er ikke alltid en forbedring. Behold den korrelerte underspørringen når:

  • Det ytre datasettet er lite, slik at kostnaden per rad er ubetydelig.
  • Den korrelerte kolonnen er godt indeksert, og optimalisatoren allerede gjør spørringen om til en effektiv semi-join.
  • Lesbarhet er viktigere enn mikrooptimalisering i kode som skal vedlikeholdes.

Moderne optimalisatorer gjør ofte automatisk EXISTS om til en semi-join. Si at De vil måle med EXPLAIN før De antar at en omskriving hjelper.

Kontroll av ekvivalens

Etter enhver omskriving må De bekrefte at den returnerer de samme radene og samme kardinalitet som originalen.

  • Kontroller at radantallet stemmer.
  • Kontroller at ingen duplikater ble innført av radmangedobling i en join.
  • Kontroller at NULL- og tomme gruppe-tilfeller fortsatt oppfører seg riktig.

En rask metode er å kjøre begge versjonene og bruke EXCEPT i begge retninger. Et tomt resultat betyr at de er enige. Intervjuere setter pris på at De verifiserer i stedet for å anta.

SELECT customer_id FROM query_a
EXCEPT
SELECT customer_id FROM query_b;
-- and the reverse; both empty => equivalent

Omskriving av IN til en JOIN

En ukorrelert IN-underspørring kan ofte også skrives om til en join, men den samme advarselen om radmangedobling gjelder. IN fjerner duplikater ved medlemskapstesting, mens en join ikke gjør det.

Hvis den indre listen inneholder dupliserte nøkler, gjentar joinen de ytre radene. Bruk DISTINCT på den indre siden eller på det endelige resultatet for å få samme semantikk som IN.

-- IN subquery
SELECT c.name FROM customers c
WHERE c.customer_id IN (SELECT o.customer_id FROM orders o);

-- Join rewrite, de-duplicated to match IN
SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id;

Hurtigsjekk

Velg riktig join-omskriving for en korrelert NOT EXISTS-anti-join.

Oppsummering: Omskriving av korrelerte underspørringer til joiner

Viktigste punkter:

  • EXISTS → INNER JOIN (legg til DISTINCT for å unngå duplikater fra radmangedobling).
  • NOT EXISTS → LEFT JOIN ... WHERE key IS NULL (test en kolonne som ikke kan være NULL).
  • Korrelert skalar aggregering → JOIN en gruppert avledet tabell, eller enda bedre, bruk en vindusfunksjon.
  • Øverste rad per gruppe → ROW_NUMBER (eller RANK ved like verdier).
  • Kontroller ekvivalensen, og sjekk med EXPLAIN før De antar at en omskriving er raskere.

Å kjenne begge formene og fellen med radmangedobling er akkurat det intervjuer på mellomnivå undersøker.

Gratis å komme i gang

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 «Skrive om korrelerte underspørringer til joiner» gratis?

Ja – hele teksten i «Skrive om korrelerte underspørringer til joiner» 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 «Skrive om korrelerte underspørringer til joiner»?

Gjør korrelert logikk om til joiner eller window-funksjoner for bedre ytelse. 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 «Skrive om korrelerte underspørringer til joiner»?

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

  1. Anatomien til en korrelert underspørring
  2. Aggregater per gruppe uten GROUP BY
  3. Korrelert EXISTS og NOT EXISTS
  4. Skrive om korrelerte underspørringer til joiner
← Tilbake til Forberedelse til kodeintervjuer