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.
Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]
Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.