8 funkcji SQL, które ułatwią Ci pracę z dużymi bazami danych

Poznaj 8 funkcji SQL, które zwiększą Twoją efektywność w pracy z dużymi bazami danych – od numerowania po zaawansowaną analizę danych.
02 lipca 2025
blog
Poziom: Średnio zaawansowany

Artykuł przeznaczony dla osób znających podstawy SQL, analityków danych i programistów, którzy chcą poznać funkcje okienkowe, CTE oraz techniki budowy bardziej zaawansowanych zapytań.

Z tego artykułu dowiesz się

  • Jak używać funkcji ROW_NUMBER() i RANK() do numerowania oraz tworzenia rankingów wyników w SQL?
  • Na czym polega PARTITION BY i czym różni się od GROUP BY w analizie danych?
  • Jak wykorzystywać CTE, funkcje okienkowe (Window Functions) oraz CASE WHEN do budowy czytelnych i zaawansowanych zapytań?

Wprowadzenie do zaawansowanego wykorzystania SQL

SQL to potężny język, który pozwala nie tylko na podstawowe operacje takie jak SELECT, INSERT czy UPDATE, ale także na wykonywanie zaawansowanych analiz i manipulacji dużymi zbiorami danych. W miarę jak nasze bazy danych rosną, rośnie również potrzeba optymalizowania zapytań i wykorzystywania bardziej złożonych funkcji SQL, które pomagają efektywnie zarządzać skomplikowanymi strukturami i wydobywać wartościowe informacje.

Zaawansowane funkcje SQL umożliwiają między innymi:

  • Przypisywanie numerów do wierszy i tworzenie rankingów bez konieczności użycia podzapytania.
  • Dzielenie danych na logiczne grupy i operowanie na tych segmentach niezależnie.
  • Tworzenie czytelniejszych i bardziej modularnych zapytań za pomocą wyrażeń wspólnych (CTE).
  • Analizę danych w kontekście zbiorczym dzięki funkcjom okienkowym.
  • Dynamiczne przekształcanie wyników na podstawie warunków logicznych.

Przykładowo, zamiast tworzyć skomplikowane zagnieżdżone zapytania, można wykorzystać funkcję ROW_NUMBER() do przypisania unikalnych numerów wierszom według określonego porządku. Z kolei CASE WHEN pozwala wprowadzać warunki bez konieczności pisania wielu osobnych zapytań.

Umiejętne korzystanie z tych narzędzi znacząco wpływa na wydajność pracy z dużymi zbiorami danych, poprawiając nie tylko szybkość działania zapytań, ale także ich czytelność i łatwość utrzymania.

Funkcja 1: ROW_NUMBER() – numerowanie wierszy

Gdy pracujesz z dużymi zbiorami danych, często pojawia się potrzeba przypisania unikalnego numeru do każdego wiersza w wyniku zapytania. Właśnie w takich sytuacjach funkcja ROW_NUMBER() okazuje się niezwykle przydatna. Pozwala ona nadać każdemu rekordowi kolejny numer, zgodnie z określoną kolejnością, bez konieczności ingerowania w strukturę tabeli.

ROW_NUMBER() jest funkcją okna, co oznacza, że działa w kontekście zbioru danych zwróconego przez zapytanie, a nie na poziomie całej tabeli. Dzięki niej łatwo można na przykład:

  • wybrać pierwszy rekord z każdej grupy wyników,
  • usunąć duplikaty danych, pozostawiając tylko jeden reprezentatywny wpis,
  • zaimplementować mechanizm stronicowania wyników (pagination) w aplikacjach.

Podstawowa składnia użycia ROW_NUMBER() wygląda następująco:

SELECT kolumny, ROW_NUMBER() OVER (ORDER BY kolumna_sortowania) AS numer_wiersza FROM tabela;

Dzięki odpowiedniemu użyciu klauzuli ORDER BY wewnątrz OVER() możesz dokładnie określić, według jakiego kryterium wiersze będą numerowane. To proste, ale niezwykle skuteczne narzędzie, szczególnie gdy masz do czynienia z milionami rekordów i potrzebujesz sprawnie zarządzać wynikami zapytań.

Funkcja 2: RANK() – rangowanie wyników

W pracy z dużymi zbiorami danych często zachodzi potrzeba uporządkowania wyników według określonych kryteriów — na przykład przy przydzielaniu miejsc na podstawie wyników sprzedaży lub ocen. Funkcja RANK() w SQL umożliwia przypisanie pozycji (rangi) do każdego rekordu w ramach uporządkowanej listy.

Podstawową cechą RANK() jest to, że przypisuje tę samą rangę rekordom o identycznych wartościach w kolumnie sortowania. W przypadku równych wartości kolejne rangi są pomijane, co odróżnia ją od innych funkcji takich jak ROW_NUMBER() czy DENSE_RANK().

Przykładowe zastosowania funkcji RANK():

  • Tworzenie rankingów sprzedaży dla przedstawicieli handlowych.
  • Wyznaczanie najlepszych wyników egzaminacyjnych z uwzględnieniem remisów.
  • Analiza najpopularniejszych produktów w danej kategorii.

Oto prosty przykład użycia funkcji RANK():

SELECT 
    employee_name,
    sales_amount,
    RANK() OVER (ORDER BY sales_amount DESC) AS sales_rank
FROM sales_data;

W wyniku działania powyższego zapytania otrzymamy tabelę, w której pracownicy zostaną uporządkowani według wysokości sprzedaży, a ci z identyczną wartością sprzedaży — otrzymają tę samą rangę.

Dla lepszego zobrazowania różnic, oto krótkie porównanie zachowania funkcji RANK() i ROW_NUMBER():

PracownikSprzedażRANK()ROW_NUMBER()
Anna100011
Bartek90022
Cezary90023
Daria80044

Jak widać, funkcja RANK() przydziela tę samą rangę przy takich samych wynikach, natomiast ROW_NUMBER() zawsze nadaje unikalny numer. Jeśli chcesz jeszcze lepiej opanować zaawansowane funkcje rankingowe oraz inne techniki pracy z dużymi zbiorami danych, sprawdź nasze Kurs SQL podstawowy - praktyczne wykorzystanie języka SQL i budowa baz danych i przekonaj się, jak efektywnie wykorzystać SQL w codziennej pracy.

Funkcja 3: PARTITION BY – dzielenie danych na segmenty

W pracy z dużymi zbiorami danych często zachodzi potrzeba grupowania wyników bez utraty szczegółowości w ramach całej tabeli. W takich sytuacjach z pomocą przychodzi klauzula PARTITION BY.

PARTITION BY pozwala podzielić dane na logiczne segmenty (partycje), w ramach których można wykonywać dodatkowe operacje analityczne – takie jak numerowanie wierszy, obliczanie średnich czy sumowanie wartości. W przeciwieństwie do GROUP BY, który agreguje dane i zwraca jedno podsumowanie dla każdej grupy, PARTITION BY zachowuje wszystkie wiersze i umożliwia analizę danych w obrębie wydzielonych grup.

Podstawowe różnice między GROUP BY a PARTITION BY:

GROUP BYPARTITION BY
Agreguje dane – redukuje liczbę wierszyZachowuje wszystkie wiersze oryginalnej tabeli
Używany głównie z funkcjami agregującymiUżywany z funkcjami okienkowymi (np. ROW_NUMBER, RANK)
Brak dostępu do szczegółów w grupiePełny dostęp do danych w ramach segmentu

Przykład użycia PARTITION BY:

SELECT employee_id, department_id, salary, 
       RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
FROM employees;

W powyższym zapytaniu pracownicy są podzieleni według działów (department_id), a następnie w każdym dziale są rangowani według wynagrodzenia. Dzięki temu możemy np. łatwo znaleźć najlepiej zarabiającego pracownika w każdym dziale bez utraty dostępu do pełnych danych.

PARTITION BY jest kluczowym narzędziem w zaawansowanej analizie danych, szczególnie gdy potrzebujemy pracować na dużych zbiorach, zachowując równocześnie kontekst poszczególnych segmentów.

💡 Pro tip: Łącz PARTITION BY z ORDER BY wewnątrz funkcji okna, aby uzyskać poprawne rankingi i sumy narastające w grupach. Top-N per grupa uzyskasz przez ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) i filtr = 1 w podzapytaniu (lub via QUALIFY, jeśli wspierane).

Funkcja 4: CTE (Common Table Expressions) – zapytania rekurencyjne i złożone

Common Table Expressions (CTE) to potężne narzędzie w SQL, które pozwala na tworzenie tymczasowych wyników zapytań używanych w dalszej części instrukcji. CTE znacząco poprawiają czytelność i organizację skomplikowanych zapytań, co w pracy z dużymi bazami danych jest kluczowe.

Podstawowe zalety CTE:

  • Przejrzystość: umożliwiają podzielenie skomplikowanego zapytania na mniejsze, bardziej czytelne fragmenty.
  • Wielokrotne użycie: pozwalają odwoływać się do wyników CTE wielokrotnie w ramach jednego zapytania.
  • Rekurencyjność: umożliwiają budowanie zapytań rekurencyjnych, np. do pracy z hierarchicznymi strukturami danych.

Typowe zastosowania CTE:

ZastosowaniePrzykład
Uproszczenie złożonych zapytańŁączenie kilku kroków obliczeniowych w jednym przejrzystym bloku
Rekurencyjne przeszukiwanie danychTworzenie drzewa kategorii lub śledzenie relacji nadrzędny-podrzędny
Wyodrębnianie danych pośrednichTworzenie zestawień lub agregacji na podstawie przetworzonych wcześniej danych

Przykład podstawowego CTE:

WITH TopEmployees AS (
    SELECT EmployeeID, FirstName, LastName, Salary
    FROM Employees
    WHERE Salary > 100000
)
SELECT *
FROM TopEmployees
ORDER BY Salary DESC;

W powyższym przykładzie CTE TopEmployees pozwala najpierw wybrać pracowników o wysokich zarobkach, a następnie użyć tego zbioru jak zwykłej tabeli w kolejnym zapytaniu.

CTE stają się nieocenione, gdy musimy operować na dużych zbiorach danych, tworzyć wielopoziomowe agregacje lub obsługiwać dane o złożonej strukturze hierarchicznej. Jeśli chcesz pogłębić swoją wiedzę i sprawnie wykorzystywać CTE w praktyce, zapisz się na nasz Kurs SQL średniozaawansowany.

💡 Pro tip: CTE poprawia czytelność, ale w wielu silnikach jest rozwijane inline — wielokrotne użycie tej samej CTE może wielokrotnie wykonywać jej definicję; przy dużych danych rozważ tabelę tymczasową lub MATERIALIZED (tam, gdzie dostępne). W CTE rekurencyjnym zawsze dodaj warunek stopu i ewentualnie limit MAXRECURSION, aby uniknąć pętli.

Funkcja 5: WINDOW FUNCTIONS – analiza danych w kontekście

Window Functions w SQL to potężne narzędzia analityczne, które pozwalają wykonywać operacje na zbiorach danych bez konieczności ich grupowania czy agregowania w osobnych podzapytaniach. Dzięki nim można analizować dane w kontekście określonych "okien" (ang. windows) – czyli wybranych zestawów wierszy – bez utraty szczegółowości pojedynczych rekordów.

Podstawową różnicą między funkcjami okna a tradycyjnymi agregacjami jest to, że Window Functions zachowują wszystkie wiersze w wyniku zapytania, dodając do nich dodatkowe wartości analityczne.

Typowe zastosowania Window Functions:

  • Obliczanie sum narastających lub średnich ruchomych.
  • Porównywanie wartości między sąsiadującymi wierszami (np. różnice dzień do dnia).
  • Przypisywanie numeracji lub rang w obrębie określonych grup.

Przykład użycia:

SELECT employee_id, department_id, salary, AVG(salary) OVER (PARTITION BY department_id) AS avg_department_salary
FROM employees;

W powyższym przykładzie dla każdego pracownika wyliczana jest średnia pensja w jego dziale, nie agregując całej tabeli i nie tracąc danych o poszczególnych pracownikach.

Porównanie tradycyjnych agregacji i funkcji okna:

CechaAgregacje (GROUP BY)Window Functions
Zachowanie wierszyRedukują liczbę wierszyZachowują wszystkie wiersze
Analiza kontekstowaOgraniczonaBardzo elastyczna
Łatwość porównywaniaWymaga podzapytańBezpośrednio w jednym zapytaniu

Window Functions są nieocenionym narzędziem przy pracy z dużymi zbiorami danych, pozwalając na bardziej szczegółowe i efektywne analizy bez konieczności skomplikowanych struktur zapytań.

💡 Pro tip: Zawsze jawnie podawaj ORDER BY i klauzulę ramy, np. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW dla sum narastających — domyślne RANGE może dawać nieoczekiwane wyniki przy remisach. Aby filtrować po wyniku funkcji okna, użyj podzapytania/CTE lub klauzuli QUALIFY, jeśli silnik ją wspiera.

Funkcja 6: CASE WHEN – warunkowe przekształcanie danych

Jedną z najbardziej wszechstronnych funkcjonalności SQL jest instrukcja CASE WHEN, która umożliwia warunkowe tworzenie nowych wartości w zapytaniach. Dzięki niej możesz dynamicznie modyfikować dane w zależności od spełnienia określonych kryteriów, bez konieczności zmiany źródłowych rekordów w bazie.

CASE WHEN działa podobnie do instrukcji IF...ELSE znanych z języków programowania. W SQL pozwala to na tworzenie nowych kolumn z przekształconymi wartościami, filtrowanie danych według bardziej złożonych reguł, a także uproszczenie wyników analizy bez potrzeby pisania wielu osobnych zapytań.

Najczęstsze zastosowania CASE WHEN to:

  • przypisywanie kategorii na podstawie warunków (np. przypisanie statusu klienta na podstawie wartości zakupów),
  • obsługa wartości domyślnych w przypadku brakujących danych,
  • dynamiczne wyliczanie wartości w agregacjach lub funkcjach analitycznych.

Przykład prostego użycia CASE WHEN:

SELECT nazwisko, 
       CASE WHEN punkty >= 90 THEN 'A' 
            WHEN punkty >= 75 THEN 'B' 
            ELSE 'C' 
       END AS ocena
FROM studenci;

W powyższym przykładzie CASE WHEN pozwala przypisać ocenę w zależności od liczby punktów zdobytych przez studenta, dostosowując wynik bez konieczności ingerowania w źródłowe dane w tabeli.

Podsumowanie i dalsze kroki

Praca z dużymi bazami danych wymaga nie tylko znajomości podstaw SQL, ale przede wszystkim umiejętności korzystania z bardziej zaawansowanych funkcji, które pozwalają na efektywne analizowanie, przekształcanie i porządkowanie informacji.

Wśród kluczowych narzędzi warto wyróżnić funkcje analityczne, takie jak ROW_NUMBER() czy RANK(), które pomagają numerować lub rangować wyniki w zestawieniach. Dzięki PARTITION BY możliwe jest dzielenie danych na logiczne grupy, co znacząco ułatwia analizę segmentów.

Jeżeli natomiast potrzebujesz budować bardziej skomplikowane zapytania lub wykonywać operacje rekurencyjne, pomocne okażą się Common Table Expressions (CTE). Dla bardziej kompleksowej analizy danych warto też znać funkcje okna (WINDOW FUNCTIONS), które umożliwiają zaawansowane operacje bez konieczności agregowania danych.

Nie można również pominąć CASE WHEN — prostego, lecz niezwykle wszechstronnego narzędzia do warunkowego przekształcania danych bez potrzeby pisania skomplikowanych zapytań proceduralnych.

Opanowanie tych funkcji pozwala nie tylko na poprawę wydajności zapytań, ale także na tworzenie bardziej czytelnych, skalowalnych i łatwych w utrzymaniu rozwiązań w środowiskach pracy z dużymi zbiorami danych.

icon

Formularz kontaktowyContact form

Imię *Name
NazwiskoSurname
Adres e-mail *E-mail address
Telefon *Phone number
UwagiComments