NULL w agregacjach i złączeniach
Dowiedz się, jak NULL zachowuje się w COUNT, SUM i JOIN
NULL w agregacjach i złączeniach to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Academy zawiera 4 lekcji w sumie.
NULL zmienia obliczenia
Funkcje agregujące i złączenia traktują wartość NULL w szczególny sposób. Jeśli nie znają Państwo tych zasad, sumy i zliczenia mogą być po cichu niepoprawne.
Ta lekcja pokazuje, jak COUNT, SUM, AVG, GROUP BY i złączenia zewnętrzne współdziałają z brakującymi wartościami.
SELECT amount FROM payments;
-- amount
-- -------
-- 100
-- NULL <- missing
-- 200Funkcje agregujące pomijają NULL
Większość funkcji agregujących — SUM, AVG, MIN, MAX — po prostu pomija wartości NULL. Agregują tylko wiersze zawierające dane.
Dlatego wartość NULL w kolumnie amount nie powoduje problemu funkcji SUM; zostaje po prostu pominięta w sumie.
-- Using amounts 100, NULL, 200
SELECT
SUM(amount) AS total, -- 300 (NULL skipped)
MIN(amount) AS lo, -- 100
MAX(amount) AS hi -- 200
FROM payments;AVG także pomija NULL
AVG dzieli sumę wartości innych niż NULL przez liczbę wartości innych niż NULL. Wartości NULL są wykluczane z obu obliczeń.
To ma znaczenie: średnia dla {100, NULL, 200} wynosi 150, a nie 100 — wartość NULL nie jest liczona jako zero.
-- (100 + 200) / 2 = 150, the NULL row is ignored
SELECT AVG(amount) AS avg_amount FROM payments;
-- If you WANT NULLs counted as 0, COALESCE first:
SELECT AVG(COALESCE(amount, 0)) AS avg_with_zeros FROM payments; -- 100COUNT(*) a COUNT(column)
Ta różnica często powoduje błędy:
COUNT(*)zlicza wiersze, również te zawierające wartości NULL.COUNT(column)zlicza tylko wiersze, w których ta kolumna nie ma wartości NULL.
-- 3 rows total, but only 2 have a non-NULL amount
SELECT
COUNT(*) AS row_count, -- 3
COUNT(amount) AS has_amount -- 2
FROM payments;COUNT(DISTINCT) a NULL
COUNT(DISTINCT col) zlicza liczbę różnych wartości innych niż NULL. Wartości NULL są całkowicie wykluczane — nigdy nie zwiększają liczby wartości różnych.
Należy o tym pamiętać podczas ustalania, „ile jest unikalnych wartości X”.
-- statuses: 'paid', NULL, 'paid', 'void'
SELECT COUNT(DISTINCT status) AS distinct_statuses
FROM payments;
-- 2 (paid, void) -- NULL not countedAgregaty dla pustego zbioru
Gdy agregacja działa na zero wierszy, wynik zależy od funkcji:
COUNT(...)zwraca0.SUM,AVG,MIN,MAXzwracająNULL.
W razie potrzeby należy użyć COALESCE, aby zamienić sumę NULL na 0.
-- No rows match -> SUM is NULL, not 0
SELECT COALESCE(SUM(amount), 0) AS total
FROM payments
WHERE status = 'refunded'; -- no such rowsGROUP BY grupuje wartości NULL razem
Chociaż w innych miejscach NULL = NULL oznacza wartość nieznaną, GROUP BY umieszcza wszystkie wartości NULL w jednej grupie.
Dlatego kategoria NULL staje się osobną grupą w wynikach, co pozwala podsumować wspólnie wiersze z brakującymi danymi.
SELECT category, COUNT(*) AS n
FROM products
GROUP BY category;
-- category | n
-- ---------+---
-- books | 5
-- toys | 3
-- NULL | 2 <- all NULL categories in one groupWartości NULL ze złączeń zewnętrznych
Złączenia zewnętrzne są ważnym źródłem wartości NULL. LEFT JOIN zachowuje każdy wiersz z lewej tabeli; jeśli po prawej stronie nie ma dopasowania, kolumny prawej tabeli otrzymują wartość NULL.
Te wartości NULL oznaczają „brak pasującego wiersza”, a nie „zapisana wartość NULL”.
SELECT c.name, o.id AS order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
-- name | order_id
-- ------+---------
-- Alice | 10
-- Bob | NULL <- Bob has no ordersZliczanie dopasowań po LEFT JOIN
Aby po LEFT JOIN zliczyć tylko rzeczywiste dopasowania, należy zliczać kolumnę z prawej tabeli, która nie może mieć wartości NULL, a nie używać COUNT(*).
COUNT(o.id) pomija wiersze z wartością NULL utworzone dla niedopasowanych wierszy z lewej tabeli, dając rzeczywistą liczbę zamówień.
SELECT c.name, COUNT(o.id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;
-- Bob shows 0, not 1×NULLOdfiltrowywanie niedopasowanych wierszy
Subtelna pułapka: umieszczenie warunku dotyczącego prawej tabeli w WHERE po LEFT JOIN zmienia go w złączenie wewnętrzne, ponieważ NULL = value jest nieznane i taki wiersz zostaje odfiltrowany.
Jeśli chcą Państwo zachować niedopasowane wiersze, należy umieścić warunek w klauzuli ON albo jawnie sprawdzić wartość NULL.
-- Accidentally drops Bob (his o.status is NULL)
SELECT c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'open';
-- Keep unmatched rows: move the test into ON
SELECT c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id AND o.status = 'open';Praktyczne zasady
Proszę stosować te zasady w każdym zapytaniu zawierającym agregacje i złączenia:
- Funkcje agregujące pomijają wartości NULL (z wyjątkiem
COUNT(*)). COUNT(col)<COUNT(*), gdy col zawiera wartości NULL.SUM/AVGdla pustego zbioru ma wartość NULL — należy użyćCOALESCE.- LEFT JOIN zwraca wartości NULL dla niedopasowanych wierszy; należy zliczać klucz z prawej tabeli.
- Filtry dotyczące prawej tabeli należy umieszczać w
ON, a nie wWHERE.
SELECT c.name,
COALESCE(SUM(o.amount), 0) AS spent,
COUNT(o.id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;Szybki test
Kolumna amount zawiera w trzech wierszach wartości 100, NULL i 200. Co zwracają COUNT(*) i COUNT(amount)?
Podsumowanie
Poznali Państwo sposób, w jaki wartości NULL przepływają przez agregacje i złączenia: funkcje agregujące pomijają wartości NULL, COUNT(*) zlicza wiersze, a COUNT(col) wartości inne niż NULL, sumy dla pustego zbioru mają wartość NULL, a GROUP BY łączy wartości NULL w jedną grupę.
Poznali Państwo również fakt, że złączenia zewnętrzne generują wartości NULL dla niedopasowanych wierszy oraz dlaczego filtry dotyczące prawej tabeli należy umieszczać w ON. To kończy kurs Praca z wartościami NULL — mogą już Państwo pewnie obsługiwać brakujące dane.
-- A NULL-safe summary query
SELECT c.name,
COUNT(o.id) AS orders,
COALESCE(SUM(o.amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name
ORDER BY total_spent DESC;Ucz się SQL dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 46
- Lekcje
- 183
Często zadawane pytania
Czy lekcja „NULL w agregacjach i złączeniach” jest bezpłatna?
Tak — pełny tekst „NULL w agregacjach i złączeniach” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Academy, przejdź na CoddyKit PRO. Kurs SQL Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „NULL w agregacjach i złączeniach”?
Dowiedz się, jak NULL zachowuje się w COUNT, SUM i JOIN Ćwiczysz SQL Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Academy?
Nie wymagamy żadnego doświadczenia. SQL Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „NULL w agregacjach i złączeniach”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Academy?
Tak. Każda lekcja SQL Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Co naprawdę oznacza NULL
- IS NULL i IS NOT NULL
- COALESCE i NULLIF
- NULL w agregacjach i złączeniach