
Kiedy zaczynałem pracę z SQL-em, miałem dokładnie tę samą reakcję, którą ma większość osób uczących się baz danych: „Po co mi to kolejna rzecz? Przecież SELECT, JOIN i GROUP BY już działają.”
No właśnie — działają. Ale do czasu.
W pewnym momencie zaczynasz pisać coraz bardziej rozbudowane zapytania. Każdy SELECT ma w sobie kolejnego SELECT-a, który ma w sobie jeszcze jednego SELECT-a… i nagle patrzysz na kod, którego sam nie jesteś w stanie odczytać. A co dopiero wyjaśnić komuś innemu.
Wtedy właśnie pojawia się on — CTE, czyli Common Table Expression, a tak naprawdę komenda WITH, którą możesz potraktować jak sposób na „odłożenie” części logiki na bok, nadanie jej nazwy i ponowne użycie w dalszej części zapytania.
W tej lekcji pokażę ci, jak działają CTE, dlaczego są tak czytelne, jak je wykorzystuję w praktyce i jak dzięki nim zbudować wieloetapowe zapytanie, które mimo złożoności czyta się jak fragment prostego kodu. To wszystko na przykładzie realnego case’u biznesowego — dokładnie takiego, jaki możesz spotkać w pracy analityka danych.
H3: Od subquery do czytelnego kodu
Poprzednia lekcja w kursie dotyczyła subquery — czyli SELECT-ów umieszczanych wewnątrz innych SELECT-ów. To bardzo potężne narzędzie i możesz za jego pomocą zrobić naprawdę wiele: porównywać wartości z innymi wartościami, filtrować dane, generować agregaty, liczyć maksima, minima i wszystko, co tylko potrzebujesz.
Ale subquery mają jedną wadę: gdy kod zaczyna być większy, robi się po prostu nieczytelny.
I o ile czasem można to przeboleć — na przykład w szybkiej analizie robionej jednorazowo — to w pracy analityka często liczy się nie tylko efekt, ale też czytelność i możliwość utrzymania kodu.
Dlatego zamiast budować SELECT w SELECT-cie w SELECT-cie… wolę coś znacznie bardziej uporządkowanego — właśnie CTE.
H3: Czym jest CTE (Common Table Expression)?
CTE to tak naprawdę tabela tymczasowa utworzona „w locie”.
Nie istnieje w bazie fizycznie.
Istnieje tylko podczas wykonywania zapytania.
Budujesz ją w taki sposób:
WITH nazwa_tabeli AS ( SELECT ... FROM ... ) SELECT * FROM nazwa_tabeli;Prawie jak subquery, ale o wiele czytelniej.
Możesz przygotować jedną taką tabelę, albo — jeżeli potrzebujesz — kilka na raz. Oddzielasz je przecinkami, a każda dostaje własną nazwę i własny SELECT.
Najważniejsze jest to, iż możesz w czytelny sposób rozbić problem na etapy.
To jest dokładnie ten moment, w którym osoba zaczynająca pracę z SQL-em mówi:
„Wow, dlaczego nikt mi tego wcześniej nie pokazał?”

Opanuj SQL z moim kursem!
Poznasz zarówno podstawy, jak i zaawansowane zapytania analityczne (CTE, subqueries, window functions). Nauczysz się pracować na różnych silnikach – na kursie pracujemy zarówno na MySQL, jak i na Postgres. Wszystko zainstalujemy na Twoim komputerze, plus dostaniesz mnóstwo zestawów danych do ćwiczeń.
H3: Budujemy pierwszy CTE – lista stanów
W naszym przykładzie biznesowym pracujemy na danych zamówień z różnych stanów USA.
Pierwszym krokiem będzie stworzenie listy wszystkich stanów.
W klasycznej wersji napisałbyś SELECT i po prostu z niego korzystał.
W wersji CTE robimy to tak:
Efekt?
Stworzyliśmy tabelę states, której możemy używać dalej — tak jak każdej innej tabeli.
Po uruchomieniu zapytania widzisz dokładnie wynik tej tabeli.
To jest pierwszy duży plus CTE: proces myślowy odzwierciedlony w kodzie.
H3: Dodajemy kolejne warstwy logiki
W analizie, którą wykonujemy, potrzebujemy trzech kluczowych zestawień:
- Liczby wszystkich zamówień w całej bazie
- Liczby zamówień per stan
- Liczby zamówień per stan i rodzaj wysyłki (shipping mode)
Każdą z tych rzeczy zrobimy jako osobne CTE.
Wszystkie zamówienia:
all_orders AS ( SELECT COUNT(*) AS total_orders FROM Orders )Zamówienia per stan:
orders_per_state AS ( SELECT State, COUNT(*) AS state_orders FROM Orders GROUP BY State )Zamówienia per stan i shipping mode:
orders_state_mode AS ( SELECT State, ShipMode, COUNT(*) AS orders_sm FROM Orders GROUP BY State, ShipMode )A teraz uwaga:
Wszystkie te bloki budujemy jeden pod drugim.
Wygląda to czytelnie i opisowo — jak scenariusz analizy.
H3: Jak SQL wykonuje CTE?
Za każdym razem, gdy odpalasz zapytanie korzystające z CTE:
- Najpierw wykonywane są wszystkie zdefiniowane CTE
- Ich wyniki są trzymane w pamięci
- Zostają użyte w końcowym SELECT-cie
Co interesujące — nie musisz ich wszystkich później wykorzystywać.
Nawet jeżeli któreś CTE zdefiniujesz, ale nie dasz go w finalnym SELECT-cie, SQL i tak je policzy.
To ważne, bo pozwala ci tworzyć logiczne etapy pracy, choćby jeżeli część z nich ostatecznie nie będzie potrzebna.
H3: Ostatni SELECT – składamy całość w jeden wynik
Mamy wszystko, czego potrzebujemy.
Czas przejść do finalnego SELECT-a, w którym:
- weźmiemy liczbę zamówień per stan i mode
- połączymy ją z liczbą zamówień per stan
- połączymy ją z liczbą zamówień globalnie
- policzymy udział procentowy
Kod w uproszczonej formie (czytelnej pod WordPress):
WITH states AS (...), all_orders AS (...), orders_per_state AS (...), orders_state_mode AS (...) SELECT osm.State, osm.ShipMode, osm.orders_sm, ops.state_orders, ao.total_orders, ROUND(osm.orders_sm * 1.0 / ops.state_orders, 4) AS ratio_state, ROUND(osm.orders_sm * 1.0 / ao.total_orders, 4) AS ratio_global FROM orders_state_mode osm JOIN orders_per_state ops ON osm.State = ops.State CROSS JOIN all_orders ao WHERE osm.State IN ('California', 'Texas', 'New York') ORDER BY osm.State, osm.ShipMode;I to jest właśnie piękno CTE:
Mimo iż logika analizy jest wieloetapowa, finalny SELECT jest krótki, logiczny, czytelny i spokojnie mieści się na jednym ekranie.
H3: Debugowanie błędów w SQL – kilka słów prawdy
W materiale, na bazie którego powstał ten artykuł, też pojawiały się błędy — brak nawiasu, brak słowa AS, drobne literówki.
Zostawiam je celowo.
Dlaczego?
Bo prawdziwa praca z SQL-em zawsze wiąże się z błędami.
Każdy analityk — choćby bardzo doświadczony — codziennie widzi przed sobą:
- „Incorrect syntax near…”
- „Column not found…”
- „Ambiguous column name…”
To normalne.
Kluczowe jest nie to, żeby pisać zapytania bez błędów, ale żeby umieć je:
- przeczytać
- zrozumieć
- poprawić
I właśnie CTE bardzo w tym pomagają.
Bo gdy masz logicznie rozbite etapy, debugowanie jest dużo prostsze.
H3: Dlaczego CTE robią taką różnicę w pracy analityka?
Z mojego doświadczenia mogę podać trzy główne powody.
1. Czytelność kodu
Duże zapytanie rozbite na mniejsze, nazwane etapy jest po prostu przyjemniejsze w pracy.
2. Logika analityczna przeniesiona do kodu
Możesz łatwo zobaczyć:
- skąd pochodzą dane,
- jak zostały przetworzone,
- jaki jest przepływ informacji.
3. Łatwość modyfikacji
Chcesz zmienić logikę liczenia?
Grzebiesz w jednym CTE — reszta zostaje bez zmian.
4. Powtarzalne bloki
Możesz tworzyć z CTE gotowe „moduły” analityczne.
To ogromna różnica, gdy pracujesz przy raportach, dashboardach lub analizach ad-hoc.
H3: Case biznesowy – policzenie udziału zamówień
Cała analiza, którą budowaliśmy, miała na celu odpowiedzieć na pytanie:
„Jaki udział mają zamówienia różnych typów wysyłki w poszczególnych stanach?”
To jest bardzo typowe pytanie biznesowe.
Przykładowo:
- jeśli w Kalifornii 60% zamówień to wysyłka First Class — to sygnał o profilu klientów
- jeśli w Teksasie dominuje Standard Class — to zupełnie inny typ odbiorcy
- jeśli globalnie jeden typ wysyłki rośnie szybciej — to wskazówka dla logistyki
Dzięki CTE mogliśmy:
- policzyć globalną liczbę zamówień
- policzyć liczbę zamówień per stan
- policzyć liczbę zamówień per stan i shipping mode
- spokojnie połączyć dane w jedną, logiczną strukturę
- policzyć udział procentowy
I co najważniejsze — cały kod jest czysty, logiczny i czytelny.
H3: CTE kontra subquery — kiedy czego używać?
Zawsze ktoś mnie o to pyta, więc odpowiem prosto:
Subquery są świetne, kiedy:
- zapytanie jest krótkie
- logika jest prosta
- wartość pomocnicza jest potrzebna tylko raz
CTE są świetne, kiedy:
- analiza ma kilka etapów
- zapytanie zaczyna się rozrastać
- chcesz mieć kod czytelny jak dokumentację
- będziesz wracał do tego kodu za miesiąc (i musisz go zrozumieć)
- pracujesz w zespole
Czyli w praktyce — w większości realnych przypadków.
H3: Drobna uwaga o wydajności
Czy CTE zawsze są szybsze?
Nie.
Czy są wolniejsze?
Też nie zawsze.
To zależy od bazy (PostgreSQL, SQL Server, BigQuery, Snowflake…), konfiguracji i optymalizatora.
W większości przypadków różnica jest marginalna, a czytelność kodu wygrywa.
W materiałach kursowych skupiam się przede wszystkim na tym, żeby dać ci narzędzia analityczne, które rozumiesz i których możesz użyć w pracy.
Optymalizacja SQL to osobny temat — i również jest w kursie omówiona.
Zapisz się do
newslettera
🎁 i zgarnij darmowe bonusy:
Poradnik Początkującego Analityka
Video - jak szukać pracy w IT
Regularne dawki darmowej wiedzy, bez spamu
Dzięki! To nie koniec...
...pamiętaj, by teraz wejść na maila i potwierdzić subskrybcję 🙂 Jeżeli nic nie doszło, to sprawdź skrzynkę ze spamem.* * * Gdy potwierdzisz newsletter, dostaniesz ostateczne potwierdzenie i obiecane prezenty w kolejnym mailu 🙂
Zakończenie – podziel się tym artykułem
CTE to jedno z tych narzędzi, które nie robi spektakularnego pierwszego wrażenia, ale zmienia kompletnie sposób pisania zapytań.
Dzięki nim twoje analizy są:
- bardziej czytelne
- logicznie uporządkowane
- łatwiejsze do debugowania
- łatwiejsze do rozwijania
Jeśli dopiero zaczynasz pracę z SQL-em — ucząc się CTE robisz krok w stronę pisania zapytań na poziomie profesjonalnego analityka.
Jeśli już pracujesz w branży — prawdopodobnie po prostu uprościsz sobie życie.
Jeśli uważasz, iż ten artykuł może komuś pomóc, podziel się nim w swoich mediach społecznościowych.
Inne interesujące artykuły:
- Jak działa FULL JOIN i SELF JOIN w SQL? Pełne wyjaśnienie na przykładach z życia analityka
- Jak sprawdzam poprawność danych w Excelu: praktyczna lekcja z ISNUMBER i AND
- Czekasz, aż poczujesz się gotowa do aplikowania? Ten moment może nie nadejść
- Czujesz, iż jesteś 10 kroków za innymi? To tylko złudzenie
- KajoDataSpace: najlepsze miejsce, żeby naprawdę wejść w świat analizy danych
Autorem artykułu jest Kajo Rudziński – analytical data architect, uznany ekspert w analizie danych, twórca KajoData oraz społeczności dla analityków KajoDataSpace.
To tyle w tym temacie. Analizujcie w pokoju!
Podobał Ci się ten artykuł 🙂?
Podziel się nim w Social Mediach 📱
>>> udostępnij go na LinkedIn i pokaż, iż codziennie uczysz się czegoś nowego
>>> wrzuć go na Facebooka, to się może przydać któremuś z Twoich znajomych
>>> Przypnij sobie tą stronkę to zakładek, może się przydać w przyszłości
Wolisz oglądać 📺 niż czytać – nie ma problemu
>>> Obserwuj i oglądaj KajoData na YouTube








