Fellen med WHERE på outer join
Hvorfor filtrering av en outer-join-kolonne i WHERE i praksis gjør den om til en inner join.
Fellen med WHERE på outer join er en gratis leksjon i Forberedelse til SQL-intervju 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 SQL-intervju, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Forberedelse til SQL-intervju inneholder totalt 4 leksjoner.
Fellen som tar alle
Dette er den vanligste feilen ved outer join som intervjuere legger inn: «Vis alle kunder og ordrene deres fra 2024, inkludert kunder uten ordrer fra 2024.»
En kandidat skriver en LEFT JOIN og legger deretter et datofilter i WHERE. Da forsvinner kundene uten ordrer fra 2024 ubemerket. LEFT JOIN blir stille omgjort til en INNER JOIN. Å forstå hvorfor er et tydelig tegn på seniornivå.
Den feilaktige spørringen
Her er feilen. Den ser rimelig ut: behold alle kunder, join ordrene deres og filtrer til 2024.
Men kunder uten ordrer, eller uten ordrer fra 2024, forsvinner fra resultatet. Kravet om å ta dem med blir dermed ikke oppfylt.
-- BUG: drops customers with no 2024 order
SELECT c.name, o.id, o.order_date
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.order_date >= '2024-01-01';Hvorfor det går galt
Husk rekkefølgen på operasjonene: JOIN kjøres først og produserer rader der kunder uten treff har NULL i alle ordrekolonnene. Deretter kjøres WHERE.
For en kunde uten treff er o.order_date NULL, så o.order_date >= '2024-01-01' evalueres til UNKNOWN, ikke true. WHERE beholder bare rader som evalueres til true, så NULL-radene filtreres bort – nettopp radene LEFT JOIN arbeidet for å bevare.
NULL slår ut filteret
Alle sammenligninger med NULL gir UNKNOWN: NULL >= '2024-01-01' er UNKNOWN, NULL = 5 er UNKNOWN, og selv NULL <> 5 er UNKNOWN.
Ettersom WHERE bare slipper gjennom rader som evalueres til TRUE, blir alle bevarte rader uten treff forkastet. Hele hensikten med outer join blir opphevet av ett enkelt WHERE-predikat på en kolonne fra høyre tabell.
Løsningen: Filtrer i ON
Flytt filteret til ON-delen. Der blir det en del av treffbetingelsen og brukes før radene bevares, slik at kunder uten treff fortsatt overlever med NULL-verdier.
-- CORRECT: filter lives in ON
SELECT c.name, o.id, o.order_date
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id
AND o.order_date >= '2024-01-01';
-- customers with no 2024 order: kept, NULL orderON kontra WHERE i én setning
Dette er regelen De bør kunne si i et intervju:
For den bevarte (outer) tabellen skal betingelser på den andre tabellen stå i ON; betingelser på selve den bevarte tabellen skal stå i WHERE.
ONavgjør hva som regnes som et treff (kjøres under joinen).WHEREfiltrerer de endelige radene (kjøres etterpå og fjerner NULL-rader).
Resultater side om side
Samme data, to plasseringer og ulike svar. Anta at Carol ikke har noen ordre fra 2024.
- Filter i WHERE: Carol forsvinner. Dette blir i praksis en inner join.
- Filter i ON: Carol vises én gang med NULL i ordrekolonnene, og kravet blir oppfylt.
Forskjellen i resultatet er hele poenget med fellen.
-- ON version output
-- Alice | 50 | 2024-03-01
-- Bob | 20 | 2024-05-02
-- Carol | NULL | NULL <-- preservedNår WHERE faktisk er riktig
Ikke alle WHERE-betingelser på en outer join er feil. Det er helt greit å filtrere den bevarte tabellen; da involveres ikke NULL-verdier fra joinen.
Og anti-joinen fra forrige leksjon bruker med hensikt WHERE o.id IS NULL for å utnytte nettopp denne oppførselen. Det viktige er å vite hvilken situasjon De står i.
-- Fine: filtering the preserved (left) table
SELECT c.name, o.id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE c.country = 'US';En metode for å oppdage feilen
Når De gjennomgår en outer join, bør De se etter predikater på den ikke-bevarte tabellen i WHERE-delen (bortsett fra IS NULL-tester for anti-join).
Hvis De ser o.someColumn = ... eller en område- eller likhetstest på outer-siden i WHERE, bør De mistenke denne fellen. Spør: «Gjør dette LEFT JOIN-en min om til en INNER JOIN?» Som regel gjør det det.
Flere betingelser
De kan kombinere begge plasseringene. Treffbetingelser på høyre tabell skal stå i ON; et reelt filter som skal brukes etter joinen på venstre tabell, skal stå i WHERE. De fungerer fint sammen.
SELECT c.name, o.id, o.amount
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id
AND o.amount > 100 -- match condition
WHERE c.signup_year = 2023; -- preserved-table filterForklare det høyt
I intervjuet bør De forklare mekanismen, ikke bare løsningen:
«Joinen kjøres først og fyller kolonnene fra høyre side med NULL for rader uten treff. Et WHERE-predikat på disse kolonnene evalueres til UNKNOWN for NULL-radene, og WHERE forkaster rader som ikke er true. Dermed kollapser outer join til en inner join. Når predikatet plasseres i ON, forblir det en treffbetingelse, og radene uten treff bevares.» Denne forklaringen treffer hver gang.
Hurtigsjekk
De må liste opp alle kunder og bare ordrene deres fra 2024, samtidig som kunder uten slike ordrer beholdes.
Oppsummering
Hvis De filtrerer en kolonne fra en ikke-bevart tabell i WHERE, blir en outer join ubemerket omgjort til en inner join, fordi NULL-verdier fra rader uten treff ikke oppfyller predikatet (UNKNOWN), og WHERE forkaster dem.
- Treffbetingelser på outer-tabellen skal stå i
ON. - Filtre på den bevarte tabellen skal stå i
WHERE. IS NULLi WHERE er den tilsiktede anti-joinen, ikke fellen.- Forklar rekkefølgen på operasjonene for å vise at De forstår den.
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 «Fellen med WHERE på outer join» gratis?
Ja – hele teksten i «Fellen med WHERE på outer join» 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 «Fellen med WHERE på outer join»?
Hvorfor filtrering av en outer-join-kolonne i WHERE i praksis gjør den om til en inner join. 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 4 av 4.
Hvor lang tid tar leksjonen «Fellen med WHERE på outer join»?
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
- LEFT JOIN og bevaring av rader uten samsvar
- Semantikken til RIGHT og FULL OUTER JOIN
- Finne rader uten samsvar (anti-join)
- Fellen med WHERE på outer join