Na pierwszy rzut oka funkcje okienkowe i agregujące wydają się podobnymi narzędziami do analizy i przetwarzania danych. Przecież oba typy wykonują obliczenia, takie jak suma, średnia, ranking itd. Ale rozkminimy, czym się różnią w praktyce.
Funkcje agregujące (GROUP BY)
Funkcje agregujące działają tak:
- Grupują wiersze według wskazanych kolumn.
- Po grupowaniu każda grupa zamienia się w jeden wiersz wyniku.
- Przykład: chcesz poznać łączny dochód dla każdego regionu.
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
Cechy szczególne: GROUP BY "ściska" dane. Jeśli używasz grupowania, wszystkie wiersze należące do jednej grupy znikają — zostaje tylko wynik agregacji.
Funkcje okienkowe (PARTITION BY)
Funkcje okienkowe natomiast:
- Zachowują oryginalną strukturę danych (żadnego ściskania ani znikania wierszy!).
- Mogą wykonywać obliczenia wewnątrz "okien" — logicznie wydzielonych grup wierszy.
Przykład: chcesz poznać udział sprzedaży każdego miasta w sumie sprzedaży jego regionu, ale zachować wszystkie dane.
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
Cechy szczególne: użycie funkcji okienkowych nie usuwa wierszy, tylko dodaje nowe wyliczone wartości do każdego wiersza.
Przykład: SUM() z GROUP BY vs SUM() z PARTITION BY
Żeby lepiej ogarnąć różnicę, zobaczmy jak SUM() działa w obu przypadkach. Załóżmy, że mamy tabelę sales_data w takim układzie:
| region | city | sales |
|---|---|---|
| North | CityA | 100 |
| North | CityB | 150 |
| South | CityC | 200 |
| South | CityD | 250 |
Sumowanie przez GROUP BY
Chcemy poznać łączną sprzedaż dla każdego regionu:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
Wynik będzie wyglądał tak:
| region | total_sales |
|---|---|
| North | 250 |
| South | 450 |
Co się stało: wiersze zostały zgrupowane po region, a każda grupa została "ściśnięta" do jednego wiersza z sumą sprzedaży.
Sumowanie przez PARTITION BY
Teraz zróbmy to samo funkcją okienkową:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
Wynik:
| region | city | sales | total_sales_by_region |
|---|---|---|---|
| North | CityA | 100 | 250 |
| North | CityB | 150 | 250 |
| South | CityC | 200 | 450 |
| South | CityD | 250 | 450 |
Co się stało: PARTITION BY nie "ściśnął" wierszy. Zamiast tego policzył sumę wewnątrz określonych okien (każdy region to osobne okno).
Kiedy używać GROUP BY, a kiedy PARTITION BY?
GROUP BY: idealny do końcowych raportów
GROUP BY przydaje się, gdy chcesz zmniejszyć ilość danych i dostać końcowe wyniki na poziomie grup. Na przykład:
- Łączna sprzedaż według miesięcy.
- Liczba zamówień według kategorii produktów.
Przykład:
SELECT category, COUNT(*) AS total_orders
FROM orders
GROUP BY category;
PARTITION BY: super do analizy i szczegółów
PARTITION BY jest spoko, gdy musisz zachować wszystkie wiersze danych i dodatkowo coś policzyć dla każdego z nich. Na przykład:
- Wyznaczyć udział sprzedaży każdego produktu w kategorii.
- Numerowanie wierszy w każdej grupie.
Przykład liczenia udziału sprzedaży:
SELECT
category,
product,
sales,
ROUND(
(sales * 100.0) / SUM(sales) OVER (PARTITION BY category),
2
) AS sales_percentage
FROM sales_data;
Przykład: użycie kilku funkcji okienkowych
Jedną z zalet funkcji okienkowych jest możliwość użycia kilku obliczeń naraz. Na przykład:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS sales_rank
FROM sales_data;
Wynik:
| region | city | sales | total_sales | sales_rank |
|---|---|---|---|---|
| North | CityB | 150 | 250 | 1 |
| North | CityA | 100 | 250 | 2 |
| South | CityD | 250 | 450 | 1 |
| South | CityC | 200 | 450 | 2 |
Zalety funkcji okienkowych nad GROUP BY
Zachowanie oryginalnych danych: GROUP BY "ściska" wiersze, a funkcje okienkowe pozwalają zachować oryginalną strukturę tabeli.
Wiele obliczeń w jednym zapytaniu: Możesz użyć kilku funkcji okienkowych z różnymi parametrami PARTITION BY i ORDER BY, zachowując dane.
Elastyczność analizy: Funkcje okienkowe pozwalają dostosować obliczenia do twoich potrzeb: sumy narastające, ranking, obliczenia udziałów i wiele więcej.
Przykład elastyczności
Spróbujmy połączyć kilka funkcji:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
AVG(sales) OVER (PARTITION BY region) AS avg_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS rank
FROM sales_data;
Wynik:
| region | city | sales | total_sales | avg_sales | rank |
|---|---|---|---|---|---|
| North | CityB | 150 | 250 | 125.0 | 1 |
| North | CityA | 100 | 250 | 125.0 | 2 |
| South | CityD | 250 | 450 | 225.0 | 1 |
| South | CityC | 200 | 450 | 225.0 | 2 |
Ograniczenia i typowe błędy
Jednym z częstych błędów jest próba użycia PARTITION BY, gdy trzeba "ściśnąć" dane. Na przykład, zamiast:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
Niektórzy próbują napisać tak:
SELECT
region,
SUM(sales) OVER (PARTITION BY region) AS total_sales
FROM sales_data;
Ale to zwróci wszystkie wiersze, nie zmniejszając ilości danych (co nie zawsze jest tym, czego chcesz).
Teraz już na pewno wiesz, kiedy używać GROUP BY, a kiedy funkcji okienkowych. To trochę jak wybór między młotkiem a śrubokrętem: oba narzędzia działają z gwoździami... ale na swój sposób.
GO TO FULL VERSION