0Pricing
SQL Academy · Lekcja

Podzapytania skorelowane

Podzapytanie zależne od wiersza zapytania zewnętrznego

Podzapytania skorelowane 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.

Czym jest skorelowane podzapytanie?

Skorelowane podzapytanie to podzapytanie, które odwołuje się do kolumny z zapytania zewnętrznego. W odróżnieniu od zwykłego podzapytania, które jest wykonywane raz i zwraca stały wynik, skorelowane podzapytanie jest wykonywane dla każdego wiersza przetwarzanego przez zapytanie zewnętrzne.

Dzięki temu skorelowane podzapytania są przydatne do porównań wiersz po wierszu, ale ich wykonanie jest bardziej kosztowne niż w przypadku prostych podzapytań.

Zwykłe a skorelowane podzapytanie

Najważniejsza różnica polega na tym, że zwykłe podzapytanie nie odwołuje się do zapytania zewnętrznego i może działać samodzielnie. Skorelowane podzapytanie zależy od bieżącego wiersza zewnętrznego — można w nim zauważyć alias tabeli zewnętrznej.

W poniższym przykładzie wewnętrzne SELECT odwołuje się do e1.department_id z zapytania zewnętrznego, tworząc korelację.

-- Regular subquery (runs once)
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

-- Correlated subquery (runs once per outer row)
SELECT name, salary, department_id
FROM employees e1
WHERE salary > (
  SELECT AVG(salary)
  FROM employees e2
  WHERE e2.department_id = e1.department_id
);

Przygotowanie przykładowych tabel

Utworzymy dwie tabele, których będziemy używać w całej tej lekcji: employees i departments. Zawierają one realistyczne dane pozwalające pokazać skorelowane podzapytania w różnych sytuacjach.

CREATE TABLE departments (
  id   INT PRIMARY KEY,
  name VARCHAR(50)
);

CREATE TABLE employees (
  id            INT PRIMARY KEY,
  name          VARCHAR(50),
  department_id INT REFERENCES departments(id),
  salary        NUMERIC(10,2),
  hire_date     DATE
);

INSERT INTO departments VALUES (1,'Engineering'),(2,'Sales'),(3,'HR');

INSERT INTO employees VALUES
  (1,'Alice',  1, 90000, '2020-03-01'),
  (2,'Bob',    1, 75000, '2021-06-15'),
  (3,'Carol',  2, 60000, '2019-01-10'),
  (4,'David',  2, 68000, '2022-09-01'),
  (5,'Eve',    3, 55000, '2020-07-20'),
  (6,'Frank',  1, 95000, '2018-11-05'),
  (7,'Grace',  3, 52000, '2023-02-28'),
  (8,'Henry',  2, 71000, '2021-04-12');

Pracownicy zarabiający więcej niż średnia w ich dziale

Klasyczny przypadek użycia skorelowanych podzapytań: znalezienie każdego pracownika, którego wynagrodzenie przekracza średnie wynagrodzenie w jego dziale. Zapytanie wewnętrzne ponownie oblicza średnią dla działu dla każdego wiersza pracownika w zapytaniu zewnętrznym.

SELECT e1.name, e1.department_id, e1.salary
FROM employees e1
WHERE e1.salary > (
  SELECT AVG(e2.salary)
  FROM employees e2
  WHERE e2.department_id = e1.department_id
)
ORDER BY e1.department_id, e1.salary DESC;

Używanie skorelowanych podzapytań w SELECT

Skorelowane podzapytania nie są ograniczone do klauzuli WHERE — mogą również występować na liście SELECT i obliczać wartość dla każdego wiersza. W tym przykładzie pobieramy wynagrodzenie każdego pracownika wraz ze średnim wynagrodzeniem w jego dziale, a wszystko odbywa się w jednym zapytaniu.

SELECT
  e.name,
  e.salary,
  (
    SELECT ROUND(AVG(e2.salary), 2)
    FROM employees e2
    WHERE e2.department_id = e.department_id
  ) AS dept_avg_salary
FROM employees e
ORDER BY e.department_id, e.name;

Znajdowanie najlepiej opłacanego pracownika w każdym dziale

Skorelowanego podzapytania można użyć do znalezienia pracownika z maksymalnym wynagrodzeniem w każdym dziale. Zapytanie wewnętrzne znajduje maksymalne wynagrodzenie w dziale bieżącego wiersza, a zapytanie zewnętrzne pozostawia tylko wiersz, który mu odpowiada.

SELECT e1.name, e1.department_id, e1.salary
FROM employees e1
WHERE e1.salary = (
  SELECT MAX(e2.salary)
  FROM employees e2
  WHERE e2.department_id = e1.department_id
)
ORDER BY e1.department_id;

EXISTS ze skorelowanym podzapytaniem

Operator EXISTS jest często używany razem ze skorelowanymi podzapytaniami. Zwraca TRUE, jeśli zapytanie wewnętrzne zwróci co najmniej jeden wiersz. W tym przykładzie wyświetlamy wszystkie działy, w których zatrudniono co najmniej jednego pracownika przed 2021 rokiem.

SELECT d.name AS department
FROM departments d
WHERE EXISTS (
  SELECT 1
  FROM employees e
  WHERE e.department_id = d.id
    AND e.hire_date < '2021-01-01'
);

NOT EXISTS ze skorelowanym podzapytaniem

NOT EXISTS działa odwrotnie — zwraca TRUE, gdy skorelowane podzapytanie nie znajduje żadnych pasujących wierszy. Jest to przydatne do wyszukiwania rekordów nadrzędnych, które nie mają rekordów podrzędnych, na przykład działów bez pracowników.

SELECT d.name AS department_without_employees
FROM departments d
WHERE NOT EXISTS (
  SELECT 1
  FROM employees e
  WHERE e.department_id = d.id
);

Skorelowane podzapytanie w UPDATE

Skorelowane podzapytania działają również wewnątrz instrukcji UPDATE. Poniższy przykład dodaje kolumnę dept_avg, a następnie używa skorelowanego podzapytania do uzupełnienia jej średnim wynagrodzeniem w dziale każdego pracownika.

ALTER TABLE employees ADD COLUMN dept_avg NUMERIC(10,2);

UPDATE employees e1
SET dept_avg = (
  SELECT ROUND(AVG(e2.salary), 2)
  FROM employees e2
  WHERE e2.department_id = e1.department_id
);

SELECT name, salary, dept_avg FROM employees ORDER BY department_id, name;

Skorelowane podzapytanie w DELETE

Skorelowanego podzapytania można również użyć w instrukcji DELETE do usuwania wierszy na podstawie danych z powiązanej tabeli. Poniższe zapytanie usuwa pracowników, których wynagrodzenie stanowi mniej niż 60% średniego wynagrodzenia w ich dziale — jest to wzorzec czyszczenia danych.

DELETE FROM employees e1
WHERE e1.salary < (
  SELECT AVG(e2.salary) * 0.60
  FROM employees e2
  WHERE e2.department_id = e1.department_id
);

SELECT name, salary, department_id FROM employees ORDER BY department_id;

Wskazówka dotycząca wydajności: podzapytanie skorelowane a JOIN

Skorelowane podzapytania są wykonywane raz dla każdego wiersza zewnętrznego, co może działać wolno w przypadku dużych tabel. Wiele skorelowanych podzapytań można przepisać jako JOIN z tabelą pochodną lub CTE, aby uzyskać lepszą wydajność. Należy znać oba wzorce i wybierać między nimi na podstawie czytelności oraz planu wykonania.

-- Correlated version (potentially slower)
SELECT e1.name, e1.salary
FROM employees e1
WHERE e1.salary > (
  SELECT AVG(e2.salary)
  FROM employees e2
  WHERE e2.department_id = e1.department_id
);

-- Equivalent JOIN + derived table (often faster)
SELECT e.name, e.salary
FROM employees e
JOIN (
  SELECT department_id, AVG(salary) AS avg_sal
  FROM employees
  GROUP BY department_id
) dept_avg ON dept_avg.department_id = e.department_id
WHERE e.salary > dept_avg.avg_sal;

Szybki test

Sprawdźmy Państwa znajomość skorelowanych podzapytań.

Podsumowanie: skorelowane podzapytania

W tej lekcji poznali Państwo skorelowane podzapytania, które odwołują się do kolumny z zapytania zewnętrznego i są ponownie wykonywane dla każdego wiersza zewnętrznego. Najważniejsze informacje:

  • Mogą występować w instrukcjach SELECT, WHERE, UPDATE i DELETE.
  • EXISTS / NOT EXISTS naturalnie współpracują ze skorelowanymi podzapytaniami, umożliwiając sprawdzanie powiązanych wierszy.
  • Są elastyczne, ale mogą działać wolno — gdy wydajność ma znaczenie, warto rozważyć przepisanie ich jako JOIN.
  • To alias tabeli zewnętrznej wewnątrz podzapytania tworzy korelację.

Często zadawane pytania

Czy lekcja „Podzapytania skorelowane” jest bezpłatna?

Tak — pełny tekst „Podzapytania skorelowane” 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 „Podzapytania skorelowane”?

Podzapytanie zależne od wiersza zapytania zewnętrznego Ć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 „Podzapytania skorelowane”?

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

  1. Podzapytania skorelowane
  2. EXISTS i NOT EXISTS
  3. IN a ANY i ALL
  4. Wydajność EXISTS a JOIN
← Powrót do SQL Academy