NULL'er i aggregater, joins og DISTINCT
Sådan opfører NULL sig forskelligt ved gruppering, join og entydighed
NULL'er i aggregater, joins og DISTINCT er en gratis Forberedelse til SQL-interview-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Forberedelse til SQL-interview, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Forberedelse til SQL-interview-kurset indeholder 4 lektioner i alt.
NULL på tre overraskende steder
NULL opfører sig ikke ens overalt. Den sidste lektion dækker de tre sammenhænge, hvor adfærden oftest overrasker kandidater: aggregeringer, JOINs og DISTINCT / GROUP BY.
Den gennemgående pointe er, at aggregeringer og filtrering behandler NULL som 'spring mig over', mens gruppering og DISTINCT behandler NULL som 'en værdi, der er lig med andre NULL-værdier'. Det er netop denne inkonsekvens, interviewere undersøger.
Hvis du mestrer dette, har du dækket de mest almindelige NULL-spørgsmål i SQL-screeninger.
Aggregeringer ignorerer NULL
Hovedreglen er: aggregeringsfunktioner springer NULL over. SUM, AVG, MIN, MAX og COUNT(column) ignorerer alle NULL-input fuldstændigt i stedet for at behandle dem som nul.
Det er grunden til, at AVG kan returnere et andet tal, end du forventer. Den dividerer summen af værdier, der ikke er NULL, med antallet af værdier, der ikke er NULL, ikke med det samlede antal rækker.
-- 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(*) sammenlignet med COUNT(column)
Det mest stillede spørgsmål om NULL i aggregeringer. COUNT(*) tæller rækker, også dem med NULL-værdier. COUNT(column) tæller kun rækker, hvor kolonnen er ikke NULL.
Forskellen mellem dem er derfor præcis antallet af NULL-værdier i kolonnen. COUNT(DISTINCT column) går et skridt videre og ignorerer også NULL, samtidig med at dubletter 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 sammenlignet med SUM/COUNT(*): En klassisk fælde
Interviewere spørger: 'Er AVG(x) det samme som SUM(x) / COUNT(*)?' Svaret er nej, når der findes NULL-værdier.
AVG(x) er lig med SUM(x) / COUNT(x) og dividerer med antallet af værdier, der ikke er NULL. Hvis du i stedet dividerer med COUNT(*), behandles NULL-værdier, som om de var nul, og gennemsnittet bliver for lavt.
Hvis du faktisk ønsker, at NULL-værdier skal tælle som nul, skal du angive det eksplicit 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;Specialtilfældet med aggregering, hvor alt er NULL
Hvad returnerer en aggregering, når alle inputværdier er NULL, eller når der ikke er nogen rækker? Her er en præcis sondring, som interviewere gerne vil høre:
SUM,AVG,MINogMAXover rækker, hvor alle værdier er NULL, eller over nul rækker, returnerer NULL.COUNTreturnerer altid 0, aldrig NULL.
Hvis en rapport viser tomme totaler, er en SUM med kun NULL-værdier en sandsynlig årsag. Pak den ind i COALESCE for at 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 JOIN's ON-klausul er NULL = NULL stadig UNKNOWN, så NULL-nøgler matcher aldrig i en equi-join. To rækker, der begge har en NULL-værdi som JOIN-nøgle, bliver ikke sat sammen.
Det er en fælde for personer, der JOIN'er på valgfrie fremmednøgler. Hvis matchning af NULL med NULL er den tilsigtede adfærd, skal du bruge en NULL-sikker operator (IS NOT DISTINCT FROM eller <=>) fra den tidligere lektion.
-- 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-værdier genereret af ydre JOINs
Ydre JOINs genererer NULL-værdier for rækker uden match. Efter et LEFT JOIN er alle kolonner på højre side NULL for de venstre rækker, der ikke fandt et match.
Det er grundlaget for mønsteret anti-join: Filtrer med WHERE right_table.key IS NULL for at finde rækker uden match, f.eks. kunder uden ordrer.
Vær dog forsigtig: Filtrering af en kolonne fra et ydre JOIN i WHERE kan ved en fejl omdanne det til et indre JOIN igen. Det er emnet for den næste 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-fælden ved WHERE på ydre JOINs
En klassisk fælde. Du laver et LEFT JOIN med orders og tilføjer derefter WHERE o.status = 'shipped'. Pludselig forsvinder kunder uden ordrer, så dit ydre JOIN i praksis bliver til et indre JOIN.
Hvorfor? For rækker uden match er o.status NULL, og NULL = 'shipped' er UNKNOWN, så WHERE fjerner dem. Hvis du vil bevare rækker uden match, skal du flytte betingelsen ind i ON-klausulen i stedet.
-- 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-værdier som ens
Her er den inkonsistens, der overrasker alle. Aggregatfunktioner springer NULL over, men DISTINCT beholder præcis én NULL-værdi og behandler alle NULL-værdier som dubletter af hinanden.
Så SELECT DISTINCT bonus over værdierne 100, 100, NULL, NULL returnerer tre rækker: 100, NULL, og ikke mere. De to NULL-værdier samles til én, selvom NULL = NULL andre steder evalueres til UNKNOWN.
-- bonus: 100, 100, NULL, NULL, 200
SELECT DISTINCT bonus FROM employees;
-- Returns: 100, 200, NULL (the two NULLs become one row)GROUP BY samler NULL-værdier i én gruppe
GROUP BY følger samme regel som DISTINCT: alle NULL-nøgler samles i en enkelt gruppe. Det er det modsatte af sammenligningslogikken, hvor NULL-værdier aldrig er lig med hinanden.
Hvis du grupperer efter en kolonne, der kan være NULL, får du altså én række, som repræsenterer alle poster med NULL som nøgle. Det er som regel det, du ønsker i rapporter. Nævn denne kontrast mellem gruppering og sammenligning for at vise dyb forstå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 themVigtige pointer til jobsamtalen
Den samlede forklaring, der imponerer interviewere:
- Aggregatfunktioner ignorerer NULL; AVG dividerer med COUNT(column), ikke COUNT(*).
- COUNT(*) tæller rækker; COUNT(col) og COUNT(DISTINCT col) springer NULL over.
- SUM/AVG/MIN/MAX over ingen rækker returnerer NULL; COUNT returnerer 0.
- I joins matcher NULL-nøgler aldrig; hvis du filtrerer en kolonne fra et outer join i WHERE, bliver det i stilhed til et inner join.
- DISTINCT og GROUP BY behandler alle NULL-værdier som ens, hvilket er det modsatte af sammenligningslogikken.
Kort sagt: »NULL ignoreres ved aggregering og sammenligning, men grupperes sammen ved deduplikering.«
Hurtigt tjek
Test kontrasten mellem gruppering og aggregering.
Opsummering
Du er nu færdig med NULL-håndtering til jobsamtaler:
- Aggregatfunktioner springer NULL over; AVG dividerer med antallet af ikke-NULL-værdier, og en SUM, hvor alle værdier er NULL, er NULL, mens COUNT er 0.
COUNT(*)medtager rækker med NULL;COUNT(col)gør ikke, og forskellen er lig med antallet af NULL-værdier.- Join-nøgler, der er NULL, matcher aldrig; filtrering af kolonner fra et outer join i WHERE kan få det til at blive til et inner join.
- DISTINCT og GROUP BY samler alle NULL-værdier i én gruppe, hvilket er det omvendte af sammenligningslogikken.
Husk mantraet: NULL ignoreres ved aggregering og sammenligning, men grupperes sammen ved deduplikering. Den ene indsigt besvarer de fleste spørgsmål om NULL ved jobsamtaler.
Lær SQL med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “NULL'er i aggregater, joins og DISTINCT” gratis?
Ja — hele teksten til “NULL'er i aggregater, joins og DISTINCT” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Forberedelse til SQL-interview-kurset, skal du opgradere til CoddyKit PRO. Forberedelse til SQL-interview-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “NULL'er i aggregater, joins og DISTINCT”?
Sådan opfører NULL sig forskelligt ved gruppering, join og entydighed Du øver dig i Forberedelse til SQL-interview med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Forberedelse til SQL-interview?
Der kræves ingen tidligere erfaring. Forberedelse til SQL-interview på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “NULL'er i aggregater, joins og DISTINCT”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Forberedelse til SQL-interview-lektion?
Ja. Alle Forberedelse til SQL-interview-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Treværdilogik og UNKNOWN
- IS NULL, IS NOT NULL og NULL-sikker lighed
- COALESCE, NULLIF og ISNULL
- NULL'er i aggregater, joins og DISTINCT