Kawałek Kodu

Zaczynasz przygodę z bazami danych. Stworzyłeś pierwszą. Tworzysz tabele. Wypełniasz danymi. Kreujesz pierwsze zapytania wkraczając w fascynujący świat klauzuli WHERE. Już chcesz wykrzyczeć swoją radość całemu światu, możnaby rzecz zJOINować się z nim, ale niestety kolejne zapytania z JOIN podcinają Ci skrzydła.

Błąd SQL (1054): Unknown column 'xxx' in 'on clause'

Ale jak to możliwe skoro ewidentnie kolumna jest. Przecież wczoraj ją tworzyłeś. Nie zrobiłeś też literówki. Wczoraj działało, a dziś nie działa! A dodałeś tylko jeden JOIN...
Jeśli masz tylko podcięte skrzydła, to choć zostawmy je w takim stanie. Zaraz odrosną.

Posłużmy się przykładem (myślę, że przez analogię łatwo dopasujesz rozwiązanie do swojego zapytania):

SELECT t1.*
FROM tabela AS t1
INNER JOIN tabela2 AS t2 ON t2.id=t1.id

Działa? Działa. To było to wczorajsze, wspaniałe zapytanie. Wspaniałe...
Dziś wygląda tak:

SELECT t1.*
FROM tabela AS t1, tabela AS t3
INNER JOIN tabela4 AS t4 ON t4.id=t3.id
INNER JOIN tabela2 AS t2 ON t2.id=t1.id

Działa? Nie działa. Otrzymujesz informację, że t1.id jest nieznaną kolumną.
Wszystko wygląda niby prawidłowo.

Dlaczego więc kolumna id z tabeli t1 "nie jest znana"?

Problem tkwi w ewaluacji tak zbudowanego zapytania, a dokładnie ważności operatora przecinka oraz złączenia JOIN. Przecinek ma mniejszy priorytet niż JOIN. O ile pierwsze złączenie nastąpiło z tabelą t3, która wyliczona jest dokładnie przed nim, o tyle drugi JOIN próbuje dokonać swych działań na tabeli t1, choć w jego zasięgu jest również tabela t3 (obydwa JOIN oraz tabela t3 stanowią wspólną sekcję podczas parsowania składni zapytania).

Jakie jest rozwiązanie?

Grupowanie, to rozwiązanie. Nie mam tu na myśli klauzuli GROUP BY, ale po prostu użycie nawiasów, które oddzielą nam tabele wyliczone we FROM od JOINów (pewnie pamiętasz z podstawówki jak pomocne są nawiasy przy nadawaniu priorytetów działaniom i takim wcinkom jak ta).

Zmieniamy więc na:

SELECT t1.*
FROM (tabela AS t1, tabela AS t3)
INNER JOIN tabela4 AS t4 ON t4.id=t3.id
INNER JOIN tabela2 AS t2 ON t2.id=t1.id

i cieszymy się wynikiem zapytania.

A tak nawiasem mówiąc, podobny problem możesz mieć przy jednym złączeniu. Przykładem niech będzie:

SELECT t1.*
FROM tabela AS t1, tabela AS t2
INNER JOIN tabela3 AS t3 ON t3.id=t2.id AND t3.id=t1.id

Tutaj również nie będzie znana kolumna t1.id, ponieważ wedle tej składni, złączenie ma nastąpić tylko z t2, więc drugi warunek złączenia odnosi się do tabeli poza zasięgiem.

Muszę teraz wziąć w nawias fakt, że chcesz jak najszybciej wrócić do budowania kolejnych zapytań, dlatego życzę Ci owocnych JOINów.

 

Przydatne linki:
JOIN i przecinek w MySQL