CodeGym /Kursy /SQL SELF /Typowe błędy przy użyciu JOIN

Typowe błędy przy użyciu JOIN

SQL SELF
Poziom 12, Lekcja 4
Dostępny

No to czas pogadać o życiu. O tej stronie, której nie da się uniknąć: błędy. Łapanie, poprawianie i rozumienie błędów — to obowiązkowa część pracy z danymi. Zobaczmy, na jakie miny można wpaść przy pracy z JOIN w SQL i jak je ominąć.

Błąd 1: Pominięcie warunku łączenia — powstaje iloczyn kartezjański

Najczęstszy błąd — zapomnieć podać warunek łączenia, używając ON. Wtedy powstaje iloczyn kartezjański, gdzie każdy wiersz z pierwszej tabeli łączy się z każdym wierszem z drugiej. W efekcie dostajesz ogromną liczbę wierszy, które nie mają sensu i tylko mieszają w głowie.

Przykład. Załóżmy, że mamy takie tabele:

Studenci (students):

student_id name
1 Otto
2 Anna

Kursy (courses):

course_id course_name
101 Matematyka
102 Historia

Teraz napiszemy zapytanie, zapominając o ON:

SELECT *
FROM students
JOIN courses;

Wynik:

student_id name course_id course_name
1 Otto 101 Matematyka
1 Otto 102 Historia
2 Anna 101 Matematyka
2 Anna 102 Historia

Nie wygląda to na prawdę, co? Ten koszmar to iloczyn kartezjański.

Jak naprawić: użyj ON, żeby wskazać, jak dane w tabelach są powiązane.

SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;

I tu pojawia się nowy rozdział błędów...

Ochrona przed głupotą

To tak częsty problem, że w PostgreSQL zabroniono używania JOIN bez ON i warunku.

Jeśli chcesz połączyć każdy wiersz z każdym, możesz użyć składni bez JOIN:

SELECT *
FROM students, courses;

Jeszcze jeden, trzeci przypadek - kiedy JOIN bez ON działa:

  • Z NATURAL JOIN — automatycznie dobiera kolumny o tych samych nazwach.
  • Z USING — podajesz listę kolumn, po których łączysz tabele.
  • CROSS JOIN — zawsze bez warunku - to samo co iloczyn kartezjański.

Błąd 2: Złe warunki łączenia

Czasem podajesz warunek łączenia, ale robisz to źle. Na przykład łączysz tabele nie po kluczach, tylko po niepowiązanych danych.

Załóżmy, że chcemy dostać listę studentów i kursów, na które są zapisani, ale mylimy się i łączymy tabele po niepowiązanych polach:

SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;

Takie zapytanie da zły wynik, bo student_id i course_id to zupełnie inne rzeczy.

Jak naprawić: upewnij się, że używasz właściwych kolumn do łączenia. Poprawne połączenie może wyglądać tak (jeśli masz tabelę enrollments, która łączy studentów z kursami):

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Błąd 3: Duplikacja wierszy w wyniku

Kiedy dodajesz kilka JOIN do zapytania, czasem prowadzi to do duplikacji wierszy. Dzieje się tak, jeśli w tabelach JOIN są powtarzające się rekordy albo źle podałeś warunki łączenia.

Załóżmy, że student Otto jest dwa razy zapisany na ten sam kurs w tabeli enrollments.

Rekordy w enrollments:

student_id course_id
1 101
1 101

Teraz zapytanie z JOIN da taki wynik:

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Wynik:

name course_name
Otto Matematyka
Otto Matematyka

Jak naprawić: po pierwsze, sprawdź, czy w twoich tabelach nie ma duplikatów. Po drugie, jeśli to oczekiwane zachowanie, usuwaj duplikaty za pomocą DISTINCT:

SELECT DISTINCT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Błąd 4: Utrata wierszy przy użyciu INNER JOIN

INNER JOIN zwraca tylko te wiersze, które mają dopasowanie w obu tabelach. Jeśli w jednej z tabel nie ma odpowiedniej wartości, wiersz zostanie pominięty. Możesz stracić dane, jeśli źle wybierzesz typ łączenia.

Załóżmy, że mamy studenta, który nie jest jeszcze zapisany na żaden kurs:

Studenci (students):

student_id name
1 Otto
2 Anna
3 Dhany

Zapisy (enrollments):

student_id course_id
1 101
2 102

Teraz zapytanie z INNER JOIN:

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Wynik:

name course_name
Otto Matematyka
Anna Historia

A gdzie Dhany? Jeśli chcesz uwzględnić studentów bez kursów, użyj LEFT JOIN:

SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id;

Błąd 5: Zła obsługa wartości NULL

Jeśli w jednej z tabel są wiersze z pustymi (NULL) wartościami, mogą nie pojawić się w wynikach (np. przy użyciu warunków filtrowania).

Przykład: używasz LEFT JOIN, ale potem dodajesz WHERE do filtrowania.

SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name = 'Matematyka';

Teraz studenci bez kursów nie pojawią się w wyniku, nawet jeśli użyłeś LEFT JOIN.

Jak naprawić: jeśli chcesz uwzględnić wiersze bez kursów, zamień WHERE na ON albo dodaj dodatkowy warunek:

SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name IS NULL OR courses.course_name = 'Matematyka';

Błąd 6: Mieszanie typów łączeń

Myli ci się, jakiego typu łączenia użyć. Na przykład stosujesz RIGHT JOIN, chociaż można by użyć LEFT JOIN, tylko zamieniając kolejność tabel.

Jak nie mieszać:

  • Używaj LEFT JOIN, jeśli możesz. To bardziej intuicyjne.
  • Zmień kolejność tabel, żeby nie musieć używać RIGHT JOIN.
2
Zadanie
SQL SELF, poziom 12, lekcja 4
Niedostępne
Poprawa iloczynu kartezjańskiego
Poprawa iloczynu kartezjańskiego
2
Zadanie
SQL SELF, poziom 12, lekcja 4
Niedostępne
Unikanie utraty danych za pomocą `LEFT JOIN`
Unikanie utraty danych za pomocą `LEFT JOIN`
1
Ankieta/quiz
Wiele JOINów, poziom 12, lekcja 4
Niedostępny
Wiele JOINów
Wiele JOINów
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION