Förberedelse inför kodningsintervjuer · Lektion

Skriv om korrelerade underfrågor som joinar

Omvandla korrelerad logik till joinar eller fönsterfunktioner för bättre prestanda

Lektion 4 av 413 steg

Skriv om korrelerade underfrågor som joinar är en gratis lektion i Förberedelse inför kodningsintervjuer på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Förberedelse inför kodningsintervjuer, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.

Varför skriva om över huvud taget

Korrelerade underfrågor är lättlästa men kan vara långsamma: den inre frågan kan köras en gång per yttre rad. Intervjuare ber ofta kandidaten att skriva om en sådan fråga som en join eller en fönsterfunktion för att förbättra prestandan.

Målet är samma resultat med en enda genomgång av data i stället för upprepade genomsökningar av den inre frågan.

Att känna till två eller tre mönster för omskrivning och veta när de bevarar korrektheten är en central färdighet på mellannivå.

Mönster 1: EXISTS till INNER JOIN

En korrelerad EXISTS som testar om det finns minst en matchning kan ofta skrivas om till en INNER JOIN.

Var dock uppmärksam: en join kan skapa dubbletter av yttre rader om flera inre rader matchar. Lägg till DISTINCT eller använd aggregering för att återställa en rad per yttre nyckel.

-- 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;

Fällan med fan-out

Det vanligaste felet vid omskrivning är att glömma fan-out. EXISTS returnerar varje kund en gång, oavsett hur många order kunden har. En naiv join returnerar en rad per order, vilket blåser upp antalen.

Om ett efterföljande steg gör COUNT(*) eller SUM(amount) över det joinade resultatet utan noggrann gruppering blir siffrorna fel.

Fråga alltid: kan joinen mångfaldiga rader? Om svaret är ja, använd DISTINCT eller en GROUP BY för att åter slå ihop resultatet.

Mönster 2: NOT EXISTS till LEFT JOIN / IS NULL

Omskrivningen till anti-join är ett givet intervjumönster. En korrelerad NOT EXISTS blir en LEFT JOIN där den högra sidan är NULL.

Yttre rader utan matchning får NULL-värden på höger sida. Genom att filtrera på detta NULL-värde behåller du exakt de rader som saknar matchning.

-- 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;

Välj en kolumn som inte kan vara NULL

I omskrivningen med LEFT JOIN / IS NULL ska du testa en kolumn på höger sida som aldrig är NULL vid en faktisk matchning, helst joinnyckeln eller primärnyckeln.

Om du testar en nullable kolumn kan du inte skilja en verklig icke-matchning (ingen rad) från en matchad rad som helt enkelt har NULL där. Det felet returnerar felaktiga rader.

Om du använder joinnyckeln (här o.customer_id) eller o.order_id garanterar du att NULL betyder "ingen matchande rad".

Mönster 3: skalär aggregering till JOIN + GROUP BY

En korrelerad aggregering i SELECT kan ersättas med en join mot en grupperad underfråga (en härledd tabell).

Beräkna aggregeringen per grupp en gång och joina sedan tillbaka den till detaljraderna. Den inre frågan körs en enda gång i stället för en gång 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: omskrivning med en fönsterfunktion

Ofta är en fönsterfunktion den renaste omskrivningen. MAX(salary) OVER (PARTITION BY dept_id) ersätter den korrelerade aggregeringen helt, utan att någon join behövs.

Den beräknar gruppvärdet i en enda genomgång och behåller alla detaljrader. Detta är vanligtvis det svar som intervjuare helst vill se för analysfrågor.

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

Omskrivning för största N per grupp

En korrelerad underfråga som väljer den översta raden per grupp (salary = MAX per dept) kan elegant skrivas om med ROW_NUMBER.

Partitionera efter gruppen, sortera efter måttet och behåll rang 1. Använd RANK i stället om du vill ha med alla rader som delar förstaplatsen.

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 du inte bör skriva om

En omskrivning är inte alltid en förbättring. Behåll den korrelerade underfrågan när:

  • Den yttre mängden är mycket liten, så kostnaden per rad är försumbar.
  • Den korrelerade kolumnen är väl indexerad och optimeraren redan omvandlar frågan till en effektiv semi-join.
  • Läsbarhet är viktigare än mikrooptimering i kod som underhålls.

Moderna optimerare omvandlar ofta EXISTS till en semi-join automatiskt. Säg att du skulle mäta med EXPLAIN innan du antar att en omskrivning hjälper.

Verifiera likvärdighet

Efter varje omskrivning ska du bekräfta att den returnerar samma rader och samma kardinalitet som originalet.

  • Kontrollera att radantalen stämmer.
  • Kontrollera att inga dubbletter har skapats genom fan-out i en join.
  • Kontrollera att NULL- och tomgruppsfall fortfarande fungerar korrekt.

Ett snabbt sätt är att köra båda versionerna och använda EXCEPT i båda riktningarna. Ett tomt resultat betyder att de överensstämmer. Intervjuare uppskattar att du verifierar i stället för att anta.

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

Skriva om IN till en JOIN

En okorrelerad IN-underfråga kan ofta också skrivas om till en join, men samma varning om fan-out gäller. IN tar bort dubbletter bland medlemskapen, vilket en join inte gör.

Om den inre listan innehåller dubbletta nycklar upprepar joinen de yttre raderna. Använd DISTINCT på den inre sidan eller på det slutliga resultatet för att matcha IN-semantiken.

-- 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;

Snabbkontroll

Välj rätt omskrivning med join för en korrelerad NOT EXISTS-anti-join.

Sammanfattning: skriva om korrelerade underfrågor som joiner

Viktiga lärdomar:

  • EXISTS → INNER JOIN (lägg till DISTINCT för att undvika dubbletter från fan-out).
  • NOT EXISTS → LEFT JOIN ... WHERE key IS NULL (testa en kolumn som inte kan vara NULL).
  • Korrelerad skalär aggregering → JOIN mot en grupperad härledd tabell eller, ännu bättre, en fönsterfunktion.
  • Största värdet per grupp → ROW_NUMBER (eller RANK vid lika värden).
  • Verifiera likvärdigheten och kontrollera med EXPLAIN innan du antar att en omskrivning är snabbare.

Att känna till båda formerna och fällan med fan-out är precis det som intervjuer på mellannivå testar.

Gratis att börja

Lär dig Förberedelse inför kodningsintervjuer med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
90
Lektioner
360

Vanliga frågor

Är lektionen ”Skriv om korrelerade underfrågor som joinar” gratis?

Ja – hela texten till ”Skriv om korrelerade underfrågor som joinar” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Förberedelse inför kodningsintervjuer, kan Ni uppgradera till CoddyKit PRO. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.

Vad lär jag mig i ”Skriv om korrelerade underfrågor som joinar”?

Omvandla korrelerad logik till joinar eller fönsterfunktioner för bättre prestanda Ni övar på Förberedelse inför kodningsintervjuer med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Förberedelse inför kodningsintervjuer?

Du behöver inga förkunskaper. Utbildningen i Förberedelse inför kodningsintervjuer på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Skriv om korrelerade underfrågor som joinar”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Förberedelse inför kodningsintervjuer-lektionen?

Ja. Varje Förberedelse inför kodningsintervjuer-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. En korrelerad underfrågas anatomi
  2. Aggregeringar per grupp utan GROUP BY
  3. Korrelerade EXISTS och NOT EXISTS
  4. Skriv om korrelerade underfrågor som joinar
← Tillbaka till Förberedelse inför kodningsintervjuer