Co dalej po pojedynczym GROUP BY
Wykonuj agregacje na wielu poziomach
Co dalej po pojedynczym GROUP BY to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 1 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.
Ograniczenie pojedynczej klauzuli GROUP BY
Standardowa klauzula GROUP BY pozwala agregować wiersze na jednym określonym poziomie — na przykład obliczać całkowitą sprzedaż według regionu. Ale co zrobić, jeśli w tym samym zapytaniu potrzebne są również sumy według kategorii produktów oraz suma całkowita?
Powtórzenie zapytania trzy razy i użycie UNION ALL działa, ale jest rozwlekłe i wolne. SQL udostępnia trzy potężne rozszerzenia — GROUPING SETS, ROLLUP i CUBE — które elegancko rozwiązują ten problem w jednym przebiegu.
SELECT region, SUM(amount) AS total_sales
FROM sales
GROUP BY region;Przygotowanie tabeli przykładowej
W tej lekcji będziemy używać prostej tabeli sales, w której każda sprzedaż jest zapisywana wraz z region, category i amount. Utwórzmy ją i wypełnijmy danymi, aby każde kolejne zapytanie było zrozumiałe w kontekście.
CREATE TABLE sales (
id SERIAL PRIMARY KEY,
region TEXT,
category TEXT,
amount NUMERIC
);
INSERT INTO sales (region, category, amount) VALUES
('North', 'Electronics', 1200),
('North', 'Clothing', 800),
('South', 'Electronics', 950),
('South', 'Clothing', 600),
('East', 'Electronics', 1100),
('East', 'Clothing', 750);Czym są GROUPING SETS
GROUPING SETS pozwala zdefiniować wiele niezależnych poziomów grupowania w jednej klauzuli GROUP BY. Każdy zestaw na liście tworzy własną grupę wierszy, tak jakby zostały napisane osobne zapytania, a następnie połączone za pomocą UNION ALL.
Składnia wygląda następująco: GROUP BY GROUPING SETS ( (col1, col2), (col1), () ). Pusty zestaw () reprezentuje sumę całkowitą dla wszystkich wierszy.
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
()
);Odczytywanie wyników GROUPING SETS
Po uruchomieniu zapytania z GROUPING SETS wiersze z różnych poziomów grupowania są umieszczane jeden pod drugim. Kolumny, które nie należą do danego zestawu, mają w tym wierszu wartość NULL.
Na przykład wiersz należący do zestawu (region) będzie miał wartość NULL w kolumnie category, co oznacza, że ta suma obejmuje wszystkie kategorie w danym regionie. Wiersz sumy całkowitej (pusty zestaw) ma wartość NULL zarówno w kolumnie region, jak i category.
SELECT
COALESCE(region, 'ALL REGIONS') AS region,
COALESCE(category, 'ALL CATEGORIES') AS category,
SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
()
)
ORDER BY region NULLS LAST, category NULLS LAST;Wprowadzenie do ROLLUP
ROLLUP jest skrótem dla często używanej hierarchii zestawów grupowania. Dla kolumn (A, B) wyrażenie ROLLUP(A, B) automatycznie generuje zestawy: (A, B), (A) i ().
Doskonale sprawdza się to w przypadku danych hierarchicznych, takich jak rok, miesiąc i dzień albo region i kategoria. Liczba wygenerowanych zestawów zawsze wynosi n + 1, gdzie n jest liczbą wymienionych kolumn.
-- ROLLUP(region, category) is equivalent to:
-- GROUPING SETS ( (region, category), (region), () )
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY ROLLUP(region, category)
ORDER BY region NULLS LAST, category NULLS LAST;ROLLUP na trzech poziomach
Dodanie trzeciej kolumny do ROLLUP rozszerza hierarchię o kolejny poziom. ROLLUP(A, B, C) generuje cztery zestawy: (A, B, C), (A, B), (A) i ().
W poniższym przykładzie year jest poziomem zewnętrznym, a category — najbardziej szczegółowym. Zapytanie tworzy sumy częściowe na każdym etapie hierarchii oraz jeden wiersz sumy całkowitej.
SELECT
year,
region,
category,
SUM(amount) AS total
FROM (
VALUES
(2024, 'North', 'Electronics', 1200),
(2024, 'North', 'Clothing', 800),
(2024, 'South', 'Electronics', 950),
(2025, 'North', 'Electronics', 1400),
(2025, 'South', 'Clothing', 700)
) AS t(year, region, category, amount)
GROUP BY ROLLUP(year, region, category)
ORDER BY year NULLS LAST, region NULLS LAST, category NULLS LAST;Wprowadzenie do CUBE
CUBE jest jeszcze bardziej rozbudowane niż ROLLUP. Dla n kolumn generuje wszystkie 2^n możliwe kombinacje zestawów grupowania, w tym sumę całkowitą.
Dla CUBE(region, category) tworzone są zestawy: (region, category), (region), (category) i () — łącznie cztery zestawy. Jest to przydatne, gdy potrzebują Państwo sum dla przekrojów we wszystkich kierunkach, a nie tylko w ramach jednej hierarchii.
-- CUBE(region, category) produces:
-- GROUPING SETS ( (region,category), (region), (category), () )
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY CUBE(region, category)
ORDER BY region NULLS LAST, category NULLS LAST;CUBE a ROLLUP — kiedy używać którego
Wybór zależy od tego, czy wymiary mają naturalną hierarchię:
- Proszę użyć ROLLUP, gdy kolumny mają strukturę hierarchiczną (np. od kraju przez miasto do sklepu). Sumy częściowe są tworzone tylko wzdłuż jednej ścieżki.
- Proszę użyć CUBE, gdy kolumny są niezależnymi wymiarami (np. region i kategoria) i potrzebują Państwo każdego możliwego przekroju.
- Proszę użyć GROUPING SETS, gdy potrzebują Państwo pełnej kontroli, a ani ROLLUP, ani CUBE nie odpowiada dokładnie wymaganiom.
Funkcja GROUPING()
Ponieważ NULL może oznaczać zarówno rzeczywiście brakującą wartość, jak i element zastępczy grupowania, SQL udostępnia funkcję GROUPING(). Zwraca ona 1, gdy kolumna należy do wiersza agregacji nadrzędnej (wiersza zastępczego), oraz 0, gdy kolumna była faktycznie użyta do grupowania.
Pozwala to odróżnić rzeczywistą wartość NULL w kolumnie regionu od wiersza sumy częściowej obejmującego wszystkie regiony.
SELECT
region,
category,
SUM(amount) AS total,
GROUPING(region) AS is_region_subtotal,
GROUPING(category) AS is_category_subtotal
FROM sales
GROUP BY CUBE(region, category)
ORDER BY region NULLS LAST, category NULLS LAST;Etykietowanie wierszy za pomocą GROUPING()
Często stosuje się funkcję GROUPING() razem z wyrażeniem CASE, aby zamiast surowych wartości NULL wyświetlać czytelne dla użytkownika etykiety. Dzięki temu wyniki zapytania z ROLLUP lub CUBE są znacznie łatwiejsze do odczytania w raportach.
SELECT
CASE GROUPING(region)
WHEN 1 THEN 'Grand Total'
ELSE region
END AS region_label,
CASE GROUPING(category)
WHEN 1 THEN 'All Categories'
ELSE category
END AS category_label,
SUM(amount) AS total
FROM sales
GROUP BY ROLLUP(region, category)
ORDER BY GROUPING(region), region, GROUPING(category), category;Łączenie stałych kolumn z ROLLUP
W tej samej klauzuli można połączyć zwykłe kolumny GROUP BY z ROLLUP lub CUBE. Kolumny wymienione poza ROLLUP(...) są zawsze uwzględniane w każdym zestawie grupowania — nigdy nie są zwijane.
W poniższym zapytaniu year jest stałą kolumną grupowania, natomiast region i category uczestniczą w zwijaniu. Oznacza to, że otrzymują Państwo sumy częściowe dla każdego roku, a nie dla wszystkich lat łącznie.
SELECT
2024 AS year,
region,
category,
SUM(amount) AS total
FROM sales
GROUP BY 2024, ROLLUP(region, category)
ORDER BY region NULLS LAST, category NULLS LAST;Szybki test
Sprawdź, czy rozumiesz GROUPING SETS, ROLLUP i CUBE.
Podsumowanie — poza pojedynczym GROUP BY
W tej lekcji poznali Państwo trzy zaawansowane rozszerzenia SQL, które pozwalają tworzyć wiele poziomów agregacji w jednym zapytaniu:
- GROUPING SETS — pełna ręczna kontrola; pozwala wymienić dokładnie potrzebne kombinacje.
- ROLLUP — idealne rozwiązanie dla hierarchii; wykonuje zwijanie od najbardziej szczegółowego poziomu do sumy całkowitej.
- CUBE — generuje każdy możliwy przekrój wymienionych wymiarów.
Poznali Państwo również funkcję GROUPING(), która odróżnia rzeczywiste wartości NULL od zastępczych wierszy agregacji nadrzędnej, a także wzorce CASE GROUPING(...) umożliwiające tworzenie przejrzystych i czytelnych wyników raportów.
Narzędzia te są niezbędne zawsze wtedy, gdy potrzebują Państwo wielowymiarowych podsumowań — intensywnie wykorzystują je raporty w stylu tabel przestawnych, pulpity nawigacyjne i zapytania hurtowni danych.
Często zadawane pytania
Czy lekcja „Co dalej po pojedynczym GROUP BY” jest bezpłatna?
Tak — pełny tekst „Co dalej po pojedynczym GROUP BY” 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 „Co dalej po pojedynczym GROUP BY”?
Wykonuj agregacje na wielu poziomach Ć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 1 z 4.
Ile czasu zajmuje lekcja „Co dalej po pojedynczym GROUP BY”?
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 dalej po pojedynczym GROUP BY
- ROLLUP dla sum częściowych
- CUBE dla wszystkich kombinacji
- GROUPING SETS — wyjaśnienie