Pchełki SQL: LEFT JOIN

Dzisiaj coś absolutnie podstawowego, o czym jednak zdarza się zapomnieć nawet starym wyjadaczom (zwłaszcza po trzech zarwanych nockach tuż przed wypuszczeniem gotowego produktu na rynek, albo w środowisko produkcyjne).

Operator LEFT JOIN działa w ten sposób, że zwraca wszystkie rekordy z tabeli głównej…

Dla jasności, mamy takie zapytanie:

SELECT A.*, B.*
FROM A
LEFT JOIN B
  ON A.SOME_ID = B.SOME_ID
  AND A.SOME_OTHER_ID = B.SOME_OTHER_ID

„Tabelą główną” jest tu A, a „tabelą dołączaną” – B.

… wszystkie, powiadam, rekordy z tabeli głównej oraz te rekordy z tabeli dołączanej, które pasują (czyli mają takie same wartości w kolumnach SOME_ID i SOME_OTHER_ID). Jeżeli rekordów pasujących do danego SOME_ID i SOME_OTHER_ID jest po stronie tabeli B więcej niż jeden, na wyjściu dostaniemy duplikaty w kolumnach tabeli A. Jeżeli rekordów pasujących nie ma, na wyjściu dostaniemy NULL we wszystkich kolumnach tabeli B. Istotne jest tu, że LEFT JOIN – w odróżnieniu od „zwykłego” JOIN – nigdy nie wyeliminuje rekordów z tabeli głównej (A). Może je co najwyżej zwielokrotnić.

Na ogół wszyscy o tym pamiętają, ale czasem zdarza się pomyłka, o taka:

SELECT A.*, B.*
FROM A
LEFT JOIN B
  ON A.SOME_ID = B.SOME_ID
WHERE A.SOME_OTHER_ID = B.SOME_OTHER_ID

Logika niby ta sama, bo w obydwu przypadkach poszukujemy rekordów z obydwu tabel, które mają takie same wartości w kolumnach SOME_ID i SOME_OTHER_ID, ale jednak nie do końca.

Przesunięcie drugiego warunku z bloku JOIN do bloku WHERE powoduje, że warunek ten zadziała na wynikach JOIN-a, a więc odfiltruje rekordy, które mają inne wartości w kolumnach SOME_OTHER_ID. W efekcie drugie zapytanie zwróci mniej rekordów od pierwszego (rzecz jasna przy założeniu, że niedopasowane rekordy istnieją).

Uwaga na koniec: technicznie rzecz biorąc, drugie z powyższych zapytań NIE jest błędem. Jest po prostu innym zapytaniem. Czasami zachodzi potrzeba założenia filtra na wynikach generowanych przez LEFT JOIN. Trzeba tylko pamiętać o logicznej różnicy między umieszczeniem warunku w samym JOIN-ie, a umieszczeniem go w klauzuli WHERE całego zapytania.

Autor: xpil

Po czterdziestce. Żonaty. Dzieciaty. Komputerowiec. Krwiodawca. Emigrant. Rusofil. Lemofil. Sarkastyczny. Uparty. Mól książkowy. Ateista. Apolityczny. Nie oglądam TV. Uwielbiam matematykę. Walę prosto z mostu. Gram na paru instrumentach. Lubię planszówki. Słucham bluesa, poezji śpiewanej i kapel a’capella. || Kliknij tutaj po więcej szczegółów ||

Dodaj komentarz

Bądź pierwszy!

Powiadom o
avatar
wpDiscuz