Forberedelse til kodeintervjuer · leksjon

NULL-verdier i aggregater, joiner og DISTINCT

Hvordan NULL oppfører seg forskjellig ved gruppering, joining og unikhet.

Leksjon 4 av 413 trinn

NULL-verdier i aggregater, joiner og DISTINCT 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.

NULL på tre overraskende steder

NULL oppfører seg ikke likt overalt. Den siste leksjonen dekker de tre kontekstene der oppførselen oftest overrasker kandidater: aggregeringer, JOIN-operasjoner og DISTINCT / GROUP BY.

Den gjennomgående vrien er at aggregeringsfunksjoner og filtrering behandler NULL som «hopp over meg», mens gruppering og DISTINCT behandler NULL som «en verdi som er lik andre NULL-verdier». Det er nettopp denne inkonsekvensen intervjuere undersøker.

Behersker De dette, har De dekket de vanligste NULL-spørsmålene i SQL-intervjuer.

Aggregeringsfunksjoner ignorerer NULL

Hovedregelen er: aggregeringsfunksjoner hopper over NULL-verdier. SUM, AVG, MIN, MAX og COUNT(column) ignorerer alle NULL-inndata fullstendig i stedet for å behandle dem som 0.

Det er derfor AVG kan returnere et annet tall enn De forventer. Den deler summen av verdier som ikke er NULL på antallet verdier som ikke er NULL, ikke på det totale antallet rader.

-- bonus values: 100, 200, NULL
SELECT
  SUM(bonus) AS total,   -- 300 (NULL ignored)
  AVG(bonus) AS average, -- 150 = 300 / 2, not / 3
  COUNT(bonus) AS cnt    -- 2 (NULL not counted)
FROM employees;

COUNT(*) kontra COUNT(column)

Dette er det vanligste spørsmålet om NULL i aggregeringer. COUNT(*) teller rader, også rader som inneholder NULL-verdier. COUNT(column) teller bare rader der kolonnen er ikke NULL.

Forskjellen mellom dem er derfor nøyaktig antallet NULL-verdier i kolonnen. COUNT(DISTINCT column) går ett skritt videre og ignorerer også NULL-verdier, samtidig som duplikater fjernes.

SELECT
  COUNT(*)              AS rows_total,    -- all rows
  COUNT(bonus)          AS non_null_bonus, -- excludes NULLs
  COUNT(DISTINCT bonus) AS distinct_bonus, -- excludes NULLs + dups
  COUNT(*) - COUNT(bonus) AS null_bonus
FROM employees;

AVG kontra SUM/COUNT(*): En klassisk felle

Intervjuere spør: «Er AVG(x) det samme som SUM(x) / COUNT(*)?» Svaret er nei når det finnes NULL-verdier.

AVG(x) er lik SUM(x) / COUNT(x) og deler på antallet verdier som ikke er NULL. Ved å dividere med COUNT(*) i stedet behandles NULL-verdier som om de var 0, slik at gjennomsnittet blir lavere.

Hvis De faktisk vil at NULL-verdier skal telles som 0, må De uttrykke det eksplisitt med COALESCE.

-- These differ when bonus has NULLs:
SELECT
  AVG(bonus)                       AS avg_ignoring_nulls,
  SUM(bonus) * 1.0 / COUNT(*)      AS avg_nulls_as_zero,
  AVG(COALESCE(bonus, 0))          AS explicit_nulls_as_zero
FROM employees;

Kanttilfellet der alle verdier er NULL

Hva returnerer en aggregering når alle inndata er NULL, eller når det ikke finnes noen rader? Her er et presist skille som intervjuere liker:

  • SUM, AVG, MIN og MAX over rader der alle verdier er NULL, eller over ingen rader, returnerer NULL.
  • COUNT returnerer alltid 0, aldri NULL.

Hvis en rapport viser blanke totaler, er en SUM som bare inneholder NULL-verdier en sannsynlig årsak. Bruk COALESCE rundt den for å vise 0.

-- No matching rows or all bonuses NULL:
SELECT SUM(bonus) FROM employees WHERE 1 = 0;  -- NULL
SELECT COUNT(bonus) FROM employees WHERE 1 = 0; -- 0

-- Present a clean zero:
SELECT COALESCE(SUM(bonus), 0) FROM employees;

NULL i JOIN-betingelser

I en JOINs ON-klausul er NULL = NULL fortsatt UNKNOWN, så NULL-nøkler samsvarer aldri i en equi-join. To rader som begge har en NULL-verdi i JOIN-nøkkelen, kobles ikke sammen.

Dette er en vanlig felle ved sammenkobling på valgfrie fremmednøkler. Hvis det er meningen at NULL skal samsvare med NULL, trenger De en NULL-sikker operator (IS NOT DISTINCT FROM eller <=>) fra den forrige leksjonen.

-- Rows with region IS NULL on both sides do NOT match
SELECT *
FROM a JOIN b ON a.region = b.region;

-- To match NULL-to-NULL (ANSI):
SELECT *
FROM a JOIN b ON a.region IS NOT DISTINCT FROM b.region;

NULL-verdier som oppstår i ytre JOIN-operasjoner

Ytre JOIN-operasjoner oppretter NULL-verdier for rader uten samsvar. Etter en LEFT JOIN er hver kolonne på høyre side NULL for rader på venstre side som ikke fant et samsvar.

Dette er grunnlaget for mønsteret anti-join: filtrer med WHERE right_table.key IS NULL for å finne rader uten samsvar, for eksempel kunder uten ordrer.

Vær likevel forsiktig: filtrering av en kolonne fra en ytre JOIN i WHERE kan utilsiktet gjøre den om til en INNER JOIN igjen, som er temaet i neste scene.

-- Find customers who have never ordered (anti-join)
SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

NULL-fellen ved WHERE på ytre JOIN

En klassisk felle. De gjør en LEFT JOIN mot orders og legger deretter til WHERE o.status = 'shipped'. Plutselig forsvinner kunder uten ordrer, slik at den ytre JOIN-en i praksis blir en indre JOIN.

Hvorfor? For rader uten samsvar er o.status NULL, og NULL = 'shipped' er UNKNOWN, så WHERE fjerner dem. Flytt betingelsen inn i ON-klausulen i stedet for å beholde radene uten samsvar.

-- Accidental inner join: drops customers with no orders
SELECT c.name, o.status
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'shipped';

-- Correct: keep unmatched customers
SELECT c.name, o.status
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id AND o.status = 'shipped';

DISTINCT behandler alle NULL-verdier som like

Her er inkonsekvensen som overrasker alle. Aggregatfunksjoner ignorerer NULL, men DISTINCT beholder nøyaktig én NULL-verdi og behandler alle NULL-verdier som duplikater av hverandre.

SELECT DISTINCT bonus over verdiene 100, 100, NULL, NULL returnerer derfor tre rader: 100, NULL og ikke noe mer. De to NULL-verdiene slås sammen til én, selv om NULL = NULL er UNKNOWN andre steder.

-- bonus: 100, 100, NULL, NULL, 200
SELECT DISTINCT bonus FROM employees;
-- Returns: 100, 200, NULL  (the two NULLs become one row)

GROUP BY samler alle NULL-verdier i én gruppe

GROUP BY følger samme regel som DISTINCT: alle NULL-nøkler samles i én enkeltgruppe. Dette er motsatt av sammenligningslogikken, der NULL-verdier aldri er like hverandre.

Gruppering etter en kolonne som kan inneholde NULL, gir derfor én rad som representerer alle postene med NULL som nøkkel. Det er vanligvis det De ønsker i rapporter. Trekk frem denne kontrasten mellom gruppering og sammenligning for å vise dybdeforståelse.

-- All employees with NULL department form ONE group
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;
-- A single row where department is NULL totals all of them

Viktige poenger til intervjuet

Den samlede oppsummeringen som imponerer intervjuere:

  • Aggregatfunksjoner ignorerer NULL; AVG dividerer med COUNT(column), ikke COUNT(*).
  • COUNT(*) teller rader; COUNT(col) og COUNT(DISTINCT col) hopper over NULL.
  • SUM/AVG/MIN/MAX over ingen rader returnerer NULL; COUNT returnerer 0.
  • I join-operasjoner stemmer NULL-nøkler aldri overens; filtrering av en kolonne fra en outer join i WHERE gjør den i praksis stille om til en inner join.
  • DISTINCT og GROUP BY behandler alle NULL-verdier som like, altså motsatt av sammenligningslogikken.

Kortversjonen: 'NULL ignoreres ved aggregering og sammenligning, men grupperes sammen ved deduplisering.'

Hurtigsjekk

Test kontrasten mellom gruppering og aggregering.

Oppsummering

De har fullført håndtering av NULL i intervjusammenheng:

  • Aggregatfunksjoner ignorerer NULL; AVG dividerer med antallet ikke-NULL-verdier, og en SUM som bare inneholder NULL, er NULL, mens COUNT er 0.
  • COUNT(*) inkluderer rader med NULL; COUNT(col) gjør ikke det, og forskjellen tilsvarer antallet NULL-verdier.
  • Join-nøkler som er NULL, stemmer aldri overens; filtrering av kolonner fra en outer join i WHERE kan gjøre den om til en inner join.
  • DISTINCT og GROUP BY samler alle NULL-verdier i én gruppe, altså det motsatte av sammenligningslogikken.

Husk mantraet: NULL ignoreres ved aggregering og sammenligning, men grupperes sammen ved deduplisering. Denne ene innsikten besvarer de fleste intervjuspørsmål om NULL.

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 «NULL-verdier i aggregater, joiner og DISTINCT» gratis?

Ja – hele teksten i «NULL-verdier i aggregater, joiner og DISTINCT» 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 «NULL-verdier i aggregater, joiner og DISTINCT»?

Hvordan NULL oppfører seg forskjellig ved gruppering, joining og unikhet. 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 «NULL-verdier i aggregater, joiner og DISTINCT»?

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. Treverdilogikk og UNKNOWN
  2. IS NULL, IS NOT NULL og NULL-sikker likhet
  3. COALESCE, NULLIF og ISNULL
  4. NULL-verdier i aggregater, joiner og DISTINCT
← Tilbake til Forberedelse til kodeintervjuer