Lekcja 5: CTE — Spraw, Żeby Twoje Zapytania Były Tak Zorganizowane, Jak Angielskie Popołudniowe Picie Herbaty!
Witaj znowu, miłośniku danych! Dzisiaj zagłębimy się w świat Common Table Expressions (CTE) — arystokratyczny sposób, żeby Twoje skomplikowane zapytania SQL wyglądały schludnie i elegancko. Wyobraź sobie CTE jako kamerdynera dla SQL: przygotowuje wszystko z wyprzedzeniem, sprawia, że dane płyną gładko, i robi to z klasą prawdziwego dżentelmena.
Co to jest CTE i po co mi to?
CTE to takie tymczasowe zestawy wyników z nazwą, które istnieją tylko podczas wykonywania Twojego zapytania. Wyobraź sobie, że zaprosiłeś kamerdynera na herbatę. Wszystko pięknie poukłada (Twoje dane), poda do stołu (Twój CTE), a potem cichutko zniknie, kiedy skończysz. A Ty cieszysz się herbatą, nie ruszając nawet małego palca!
CTE są idealne do:
- Podzielenia skomplikowanych zapytań na bardziej czytelne części.
- Wielokrotnego użytku tych samych zapytań bez powtarzania.
- Nadania Twojemu SQL-owi elegancji godnej wieczornej filiżanki Earl Grey!
Tworzenie CTE: Użycie Klauzuli WITH
CTE definiuje się za pomocą słowa kluczowego WITH
, po którym podajesz nazwę (tak jakbyś nadawał tytuł swojemu kamerdynerowi). Potem określasz zapytanie, które tworzy CTE, i używasz go, jakby to była osobna tabela:
WITH misje_rycerzy AS (
SELECT imie, krolestwo, COUNT(misja) AS misje_ogolem
FROM misje
GROUP BY imie, krolestwo
)
SELECT * FROM misje_rycerzy;
W tym przykładzie misje_rycerzy
zlicza liczbę misji dla każdego rycerza i królestwa. Gdy już jest zdefiniowane, możesz go użyć w swoim głównym zapytaniu, co sprawia, że całość wygląda znacznie bardziej schludnie.
Wiele CTE: Jak Zaprosić Więcej Kamerdynerów do Pomocy
Można zdefiniować wiele CTE, łącząc je przecinkami. Wyobraź sobie, że chcesz zobaczyć, którzy rycerze są weteranami (ponad 3 misje) i które królestwa prowadzą w odwadze:
WITH misje_rycerzy AS (
SELECT imie, krolestwo, COUNT(misja) AS misje_ogolem
FROM misje
GROUP BY imie, krolestwo
),
rycerze_weterani AS (
SELECT imie, krolestwo
FROM misje_rycerzy
WHERE misje_ogolem > 3
)
SELECT rycerze_weterani.imie, rycerze_weterani.krolestwo
FROM rycerze_weterani
JOIN misje_rycerzy ON rycerze_weterani.imie = misje_rycerzy.imie;
Tutaj misje_rycerzy
to nasz pierwszy CTE, a rycerze_weterani
jest zbudowany na jego podstawie. To jak zaprosić drugiego kamerdynera, żeby upewnić się, że wszystko działa jak należy!
Rekursywne CTE: Kiedy Jeden Kamerdyner To Za Mało
CTE stają się jeszcze bardziej użyteczne, kiedy używasz ich rekurencyjnie. Wyobraź sobie, że chcesz stworzyć drzewo genealogiczne rycerzy: Sir Artur szkolił Sir Lancelota, który z kolei trenował Sir Galahada, i tak dalej. Dzięki rekurencyjnemu CTE możesz przejść przez całe drzewo od góry do dołu:
WITH RECURSIVE genealogia_rycerzy AS (
SELECT imie, mentor, 1 AS pokolenie
FROM rycerze
WHERE mentor IS NULL
UNION ALL
SELECT r.imie, r.mentor, g.pokolenie + 1
FROM rycerze r
JOIN genealogia_rycerzy g ON r.mentor = g.imie
)
SELECT * FROM genealogia_rycerzy;
Ten zapytanie buduje drzewo genealogiczne, zaczynając od najwyższego rycerza (który nie ma mentora) i przechodząc przez pokolenia. To jak mieć armię kamerdynerów, gdzie każdy dba o swoją gałąź rodziny!
Dlaczego CTE Są Lepsze Niż Podzapytania?
Podzapytania bywają przydatne, ale jeśli używasz ich zbyt często, szybko robi się bałagan. CTE z kolei sprawiają, że Twój SQL wygląda schludnie i przejrzyście:
- Czytelność: CTE rozbijają skomplikowane zapytania na łatwe do zrozumienia części.
- Wielokrotność Użytku: Definiujesz raz, używasz ile razy chcesz.
- Łatwe do Debugowania: Łatwiej znaleźć, gdzie coś poszło nie tak.
Więc następnym razem, gdy będziesz walczył z zapytaniem-potworem, wezwij kamerdynera CTE, żeby ogarnął bałagan w Twoim SQL-u.
Złóżmy Wszystko Razem: Wielki Bal CTE
Oto końcowy przykład, który pokaże, jak to wszystko działa:
Chcesz znaleźć wszystkich rycerzy, którzy wykonali więcej niż 3 misje, i dowiedzieć się, które królestwo ma największy odsetek takich weteranów. Rozbijmy to na kilka eleganckich CTE:
WITH misje_rycerzy AS (
SELECT imie, krolestwo, COUNT(misja) AS misje_ogolem
FROM misje
GROUP BY imie, krolestwo
),
rycerze_weterani AS (
SELECT imie, krolestwo
FROM misje_rycerzy
WHERE misje_ogolem > 3
),
odwaga_krolestwa AS (
SELECT krolestwo, COUNT(*) AS liczba_weteranow,
(COUNT(*)::float / (SELECT COUNT(*) FROM rycerze WHERE rycerze.krolestwo = odwaga_krolestwa.krolestwo)) * 100 AS procent_weteranow
FROM rycerze_weterani
GROUP BY krolestwo
)
SELECT krolestwo, procent_weteranow
FROM odwaga_krolestwa
ORDER BY procent_weteranow DESC;
Ta elegancka struktura pokazuje, jak CTE mogą sprawić, że nawet najbardziej złożone zapytania stają się łatwe do ogarnięcia.
Czego Się Dzisiaj Nauczyliśmy?
Dziś zagłębiliśmy się w świat CTE:
- Podstawowe CTE: Organizują zapytania na czytelne części.
- Wiele CTE: Można je łączyć, żeby poprawić przejrzystość.
- Rekursywne CTE: Idealne do pracy z hierarchicznymi danymi.
Co Dalej?
W następnym odcinku odkryjemy tajemnice Window Functions — narzędzi, które wyniosą Twoją analizę danych na poziom królewski!
Gotowy dodać elegancji do swoich zapytań z pomocą CTE? Załóż najlepszy SQL-garnitur i szykuj się na kolejny rozdział!