CodeGym /Kursy /SQL SELF /Użycie SELECT wewnątrz SELECT...

Użycie SELECT wewnątrz SELECT

SQL SELF
Poziom 13 , Lekcja 1
Dostępny

Wyobraź sobie, że pracujesz jako analityk na uniwersytecie (robimy przecież bazę danych dla uczelni, pamiętasz?). Poproszono cię, żebyś nie tylko wyświetlił studentów i ich oceny, ale też dodał do tabeli kolumnę z maksymalną oceną w grupie, żeby łatwo porównywać wyniki. Jak to ogarnąć? Jasne, z pomocą subquery w SELECT!

Subquery w SELECT pozwala liczyć wartości bezpośrednio podczas wykonywania głównego zapytania. To jest mega, bo możesz łączyć agregaty, złożone filtry i nawet inne zbiory danych w jednym zapytaniu.

Podstawy zagnieżdżonych zapytań w SELECT

Subquery w SELECT działa dokładnie tak, jak brzmi: wrzucasz wynik jednego SELECT do środka drugiego. Dzięki temu możesz policzyć dodatkowe wartości dla każdego wiersza wyniku.

Prosty przykład. Załóżmy, że mamy tabelę students o takiej strukturze:

student_id name group_id
1 Linda 101
2 Otto 102
3 Anna 101

I tabelę grades:

grade_id student_id grade
1 1 5
2 1 4
3 2 3
4 3 5
5 3 4

Przykład 1: Dodanie maksymalnej oceny w grupie

Zadanie: wyświetlić imiona studentów, ich oceny i maksymalną ocenę w grupie, żeby było widać, jak bardzo wyniki każdego różnią się od najlepszych w grupie.

Kod SQL:

SELECT
    s.name AS student_name,
    g.grade AS student_grade,
    (
        SELECT MAX(grade) -- to zapytanie zwraca tylko jedną wartość 
        FROM grades 
        INNER JOIN students ON grades.student_id = students.student_id
        WHERE students.group_id = s.group_id
    ) AS max_group_grade 
FROM 
    students s
INNER JOIN 
    grades g ON s.student_id = g.student_id;

Co tu się dzieje:

  1. Dla każdego studenta pobieramy jego imię i ocenę (s.name, g.grade).
  2. SELECT MAX(grade) — to subquery, które zwraca maksymalną ocenę w grupie studenta.
  3. Subquery wykonuje się dla każdego wiersza głównego zapytania i używa warunku WHERE students.group_id = s.group_id, żeby ograniczyć wybór do jednej grupy.

Przykład 2: Średnia ocena w grupie

Chcesz być jeszcze bardziej pomocny dla analityków? Dodajmy do wyniku nie tylko maksymalną, ale też średnią ocenę w grupie.

Kod SQL:

SELECT
    s.name AS student_name,
    g.grade AS student_grade,
    (
        SELECT AVG(grade) 
        FROM grades 
        INNER JOIN students ON grades.student_id = students.student_id
        WHERE students.group_id = s.group_id
    ) AS avg_group_grade
FROM 
    students s
INNER JOIN 
    grades g ON s.student_id = g.student_id;

Teraz:

  • Zamiast MAX() używamy AVG(), żeby policzyć średnią ocenę w grupie.
  • Dostajemy "na żywo" analizę danych.

Ograniczenia i wskazówki

Subquery w SELECT są mocne, ale trzeba z nimi uważać:

  1. Wydajność. Każde subquery wykonuje się dla każdego wiersza głównego zapytania. To może spowolnić SQL, jeśli tabele są duże. Na przykład, jeśli masz 1000 studentów, subquery wykona się 1000 razy!
  2. Indeksy. Żeby przyspieszyć takie zapytania, dobrze zindeksuj kolumny używane w warunkach WHERE subquery.
  3. Czytelność. Unikaj zbyt dużego zagnieżdżenia. Jeśli subquery robi się za bardzo skomplikowane, pomyśl o przeniesieniu ich do FROM albo użyciu tymczasowych tabel.

Przykłady użycia

Zobaczmy jeszcze kilka ciekawych case'ów.

Przykład 3: Liczba kursów każdego studenta

Wyświetlamy tabelę, gdzie dla każdego studenta pokazujemy liczbę kursów, na które jest zapisany. Tabela enrollments jest powiązana ze studentami przez student_id:

student_id course_id
1 201
1 202
2 201
3 203

Kod SQL:

SELECT
    s.name AS student_name,
    (
        SELECT COUNT(*) 
        FROM enrollments
        WHERE enrollments.student_id = s.student_id
    ) AS course_count
FROM 
    students s;

Tutaj subquery liczy ilość wpisów w tabeli enrollments dla każdego studenta.

Przykład 4: Flaga "prymus" dla każdego studenta

Pokażemy, czy student jest prymusem. Niech kryterium prymusa będzie to, że wszystkie jego oceny to 5.

Kod SQL:

SELECT
    s.name AS student_name,
    (
        SELECT CASE 
            WHEN MIN(g.grade) = 5 THEN 'Prymus'
            ELSE 'Nie prymus'
        END
        FROM grades g
        WHERE g.student_id = s.student_id
    ) AS status
FROM 
    students s;

Tu używamy zagnieżdżonego CASE, żeby nadać status "Prymus" tylko tym studentom, którzy mają wszystkie oceny równe 5.

Optymalizacja subquery w SELECT

Już wspomnieliśmy, że wydajność może być problemem. Oto kilka tipów, jak ją poprawić:

  1. Używaj indeksów. Jeśli subquery filtrują dane, upewnij się, że na używanych kolumnach są indeksy.
  2. Cache'uj wyniki. Czasem warto wynieść subquery do widoków (VIEW) albo tymczasowych tabel.
  3. Mniej zagnieżdżenia. Nie przesadzaj z ilością zagnieżdżeń, jeśli da się to zrobić prościej.

Subquery w SELECT otwierają masę możliwości do liczenia i analizy danych. Chociaż mogą być zasobożerne, dobrze zoptymalizowane sprawiają, że SQL jest dużo bardziej wyrazisty i elastyczny. Więc nie bój się eksperymentować i znajdować swoje sposoby na ulepszanie zapytań!

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION