Tabele Osoby i Adresy są połączone relacją jeden do wielu. Które zapytanie SQL należy wykonać, aby korzystając z tej relacji, wyświetlić nazwiska osób mieszkających w Krakowie?

A.
SELECT nazwisko FROM Osoby WHERE Miasto = 'Kraków';
B.
SELECT nazwisko FROM Osoby JOIN Adresy ON Osoby.Adresy_id = Adresy.id WHERE Miasto = 'Kraków';
C.
SELECT nazwisko FROM Osoby, Adresy WHERE Miasto = 'Kraków';
D.
SELECT nazwisko FROM Osoby JOIN Adresy ON Osoby.id = Adresy.id WHERE Miasto = 'Kraków';
To zapytanie dobrze wykorzystuje relację między tabelami Osoby i Adresy, bo łączy rekordy przez klucz obcy Osoby.Adresy_id wskazujący na klucz główny Adresy.id. Dzięki temu baza wie, który adres należy do konkretnej osoby, a warunek WHERE Miasto = 'Kraków' filtruje już tylko te połączone rekordy, w których adres znajduje się w Krakowie. Innymi słowy: najpierw robimy poprawne JOIN, a potem wybieramy interesujące nas miasto. To jest standardowe podejście w SQL przy pracy z relacjami między tabelami.
W praktyce takie zapytanie wyglądałoby np. tak: SELECT nazwisko FROM Osoby JOIN Adresy ON Osoby.Adresy_id = Adresy.id WHERE Miasto = 'Kraków';. Moim zdaniem warto od razu wyrabiać sobie nawyk dopisywania nazw tabel przy kolumnach, np. Osoby.nazwisko oraz Adresy.Miasto, bo w większych bazach często pojawiają się kolumny o tych samych nazwach. Jeszcze czytelniej byłoby użyć aliasów: SELECT o.nazwisko FROM Osoby o JOIN Adresy a ON o.Adresy_id = a.id WHERE a.Miasto = 'Kraków';. To jest zgodne z dobrymi praktykami branżowymi: jawne JOIN, jasny warunek połączenia i filtrowanie po kolumnie z właściwej tabeli.
W praktyce takie zapytanie wyglądałoby np. tak: SELECT nazwisko FROM Osoby JOIN Adresy ON Osoby.Adresy_id = Adresy.id WHERE Miasto = 'Kraków';. Moim zdaniem warto od razu wyrabiać sobie nawyk dopisywania nazw tabel przy kolumnach, np. Osoby.nazwisko oraz Adresy.Miasto, bo w większych bazach często pojawiają się kolumny o tych samych nazwach. Jeszcze czytelniej byłoby użyć aliasów: SELECT o.nazwisko FROM Osoby o JOIN Adresy a ON o.Adresy_id = a.id WHERE a.Miasto = 'Kraków';. To jest zgodne z dobrymi praktykami branżowymi: jawne JOIN, jasny warunek połączenia i filtrowanie po kolumnie z właściwej tabeli.
W tym zadaniu kluczowe jest zrozumienie, że samo wpisanie dwóch tabel po FROM nie oznacza jeszcze poprawnego użycia relacji. Jeśli podamy Osoby, Adresy i dodamy tylko warunek Miasto = 'Kraków', baza utworzy w praktyce iloczyn kartezjański ograniczony miastem. Czyli każdy rekord z tabeli Osoby może zostać zestawiony z każdym adresem z Krakowa. Wynik może wyglądać pozornie sensownie, ale logicznie jest zły, bo brakuje warunku łączącego klucz obcy z kluczem głównym. To częsty błąd, szczególnie gdy ktoś pamięta starą składnię z przecinkiem, ale zapomina o warunku relacji.
Niepoprawne jest też odwołanie się tylko do tabeli Osoby i filtrowanie po kolumnie Miasto, ponieważ według schematu kolumna Miasto znajduje się w tabeli Adresy. Baza danych nie znajdzie takiego pola w tabeli Osoby, albo zapytanie będzie niezgodne ze strukturą danych. Trzeba dołączyć tabelę, w której faktycznie zapisano miasto.
Problemem może być również mylenie klucza głównego osoby z kluczem głównym adresu. Warunek Osoby.id = Adresy.id technicznie czasem zwróci jakieś dane, ale będzie to przypadkowe dopasowanie identyfikatorów z dwóch różnych encji. Id osoby nie opisuje adresu tej osoby. Relację wskazuje dopiero pole Osoby.Adresy_id, czyli klucz obcy. Z mojego doświadczenia to jedna z ważniejszych rzeczy w SQL: nie łączymy tabel po kolumnach, które mają podobną nazwę albo podobny typ, tylko po kolumnach wynikających z projektu relacyjnego bazy. Dobre zapytanie powinno mieć jawne JOIN oraz warunek ON zgodny ze schematem relacji.
Niepoprawne jest też odwołanie się tylko do tabeli Osoby i filtrowanie po kolumnie Miasto, ponieważ według schematu kolumna Miasto znajduje się w tabeli Adresy. Baza danych nie znajdzie takiego pola w tabeli Osoby, albo zapytanie będzie niezgodne ze strukturą danych. Trzeba dołączyć tabelę, w której faktycznie zapisano miasto.
Problemem może być również mylenie klucza głównego osoby z kluczem głównym adresu. Warunek Osoby.id = Adresy.id technicznie czasem zwróci jakieś dane, ale będzie to przypadkowe dopasowanie identyfikatorów z dwóch różnych encji. Id osoby nie opisuje adresu tej osoby. Relację wskazuje dopiero pole Osoby.Adresy_id, czyli klucz obcy. Z mojego doświadczenia to jedna z ważniejszych rzeczy w SQL: nie łączymy tabel po kolumnach, które mają podobną nazwę albo podobny typ, tylko po kolumnach wynikających z projektu relacyjnego bazy. Dobre zapytanie powinno mieć jawne JOIN oraz warunek ON zgodny ze schematem relacji.