08. Łączenie tabel.txt

(48 KB) Pobierz
#165
Rozdział 8.
Łšczenie tabel

W wielu wypadkach, w trakcie wyszukiwania informacji z bazy danych okazuje się, że potrzebne dane przechowywane sš w kilku tabelach. Nawet gdy potrzebne dane znajdujš się w jednej tabeli, możemy chcieć je porównać z danymi z innej tabeli, aby na tej podstawie wybrać tylko poprawne pozycje. Dużo czasu powięcono podczas projektowania struktury na rozdzielenie danych do wielu tabel w celu eliminacji nadmiarowoci.
W celu połšczenia danych z wielu tabel w jednym zapytaniu wymagane jest złšczenie. Aby porównać dane z jednej tabeli z danymi z drugiej tabeli można wykonać złšczenie tabel lub podzapytanie (podzpytania omówiono w rozdziale 9.).
W tym rozdziale omówię różne typy zapytań złšczajšcych i  wyjanię, dlaczego wymaga ich relacyjny model baz danych.
Przedstawione wczeniej techniki wybierania danych były stosowane do pojedynczych tabel. W tym rozdziale wyjanię, jak rozszerzyć te techniki na zapytania używajšcych wielu tabel.

Połšczenia i normalizacja

Podczas projektowania tabel ważne jest wykonanie normalizacji, żeby zapewnić spójnoć danych, tak aby ta sama porcja informacji nie pojawiała się w wielu tabelach. Dzięki temu w przyszłoci unikamy problemów przy aktualizacji danych. Niestety, oznacza to koniecznoć dostępu do wielu tabel w pojedynczym zapytaniu.
Używajšc złšczeń między tabelami można wybierać informacje z wielu tabel za pomocš pojedynczej instrukcji SELECT. Daje to efekt ponownego połšczenia danych, które zostały rozdzielone do wielu tabel w trakcie normalizacji.
#166
Co to jest złšczenie?

Złšczenie (ang. join) to zapytanie, które łšczy dane z wielu tabel. Struktura standardowego zapytania wyglšda następujšco:

SELECT column_list
FROM table [ , table,...]
[ WHERE condition]

Główna różnica w składni pomiędzy instrukcjš SELECT wykorzystywanš w poprzednich rozdziałach, a instrukcjš SELECT wykorzystujšca złšczenia, polega na tym, że w częci FROM pojawiajš się deklaracje kilku tabel. Typowa pojedyncza instrukcja SELECT wyglšda następujšco:

SELECT * FROM Movies

Z drugiej strony instrukcja SELECT, która łšczy dwie tabele zawiera wiele wywołań
tabel w częci table_list:

SELECT *
FROM Movies, Studios

Problem z instrukcjš SELECT polega na tym, że zwraca ona każdš możliwš kombinację wierszy z dwóch tabel. Jeżeli tabela Movies zawiera 8 wierszy, a tabela Studios 10 wierszy to zapytanie zwróci 80 wierszy. Taki wynik jest rzadko pożšdany.
Tworzenie sensownych złšczeń wymaga spełnienia dwóch warunków. Po pierwsze, należy wybrać w każdej tabeli kolumny, które sš ze sobš w logiczny sposób powišzane z kolumnami z drugiej tabeli. Po drugie, musi być zdefiniowane kryterium okrelajšce warunki złšczenia dwóch tabel. Przyjrzyjmy się tym dwu warunkom dokładniej.

Zgodne kolumny

Aby połšczenie dwóch tabel miało sens, muszš one mieć jakie wspólne dane. Zwróć uwagę, na listingi 8.1 i 8.2, które pokazujš dane z tabel Movies i People.
----------------------------
Listing 8.1. Kolumny title i directorjdz tabeli Moyies

SELECT movie_title, director_id
FROM Movies
ORDER BY director id

MOVIE_TITLE		DIRECTOR_ID
Minerał House		1
Condependence Day		1
The Programmer		1
The Rear Windows		1
The Code Warrior		2
The Linux Files		2
Bili Durham			9
Sql Strikes Back		9
Price Kong			10
Hard Code			10
Aws

10 rows selected
----------------------------
#167
----------------------------
Listing 8.2. Kolumny person_id, person Jname i person_lname z tabeli People

SELECT person_id,   person_fname,   person_lname
FROM People
ORDER  BY  person_id

PERSON_ID	PERSON_FNAME	PERSON_LNAME
----------------------------
1	Jeff		Price
2	Chuck		Peterson
3	Brandon	Broołcs
4	Brian		Smith
5	Paul		Monk
6	Reece		Randall
7	Peter		Jong
8	Maggie 	Davies
9	Becky		Orvis
10	Carol 	Delano

10	rows selected
----------------------------

Kolumna director_id z tabeli Movies odpowiada kolumnie person_id z tabeli People. Rzeczywicie, jeli jeszcze pamiętasz dyskusję na temat projektu bazy danych z rozdziału 3., to kolumna director_id jest kluczem obcym z tabeli People. W zwišzku z tym, że te dwie kolumny odpowiadajš sobie, można ich użyć do ustanowienia złšczenia między tabelami.
W bardziej ogólnym znaczeniu kolumny z różnych tabel mogš być rozważane jako odpowiadajšce sobie (ang. join-compatybile), jeli zawierajš dane o tym samym znaczeniu. Sam fakt zgodnoci typów danych nie jest wystarczajšcy. Jeli dwie kolumny zawierajš dane typu Integer lub VARCHAR (20), to jeszcze nie wiadczy to o powišzaniu logicznym między kolumnami. Na przykład porównajmy kolumny person_id z tabeli People z kolumnš gross z tabeli Movies.
Obie kolumny zawierajš liczby, ale nie ma żadnego powišzania między danymi z tych kolumn. W zwišzku z tym utworzenie złšczenia między tabelami poprzez te dwie kolumny jest możliwe, ale nie ma sensu.
Z drugiej strony kolumny, o których wspomniałem na wstępie (director_id oraz person_id) mogš być wykorzystane do utworzenia zapytania, w którym wyszukamy imię i nazwisko reżysera każdego filmu z tabeli Movies.
----------------------------
Listing 8.3. Zapytanie łšczšce

SELECT movie_title, person_fname, person_lname
FROM Movies, People
HHERE director_id - person_id

MOVIE_TITLE		PERSON_FNAME	PERSON_LNAME
----------------------------
Minerał House	Jeff		Price
Condependence Day	Jeff		Price
The Programmer	Jeff		Price
The Rear Windows	Jeff		Price
The Code Warrior	Chuck		Peterson
The Linux Files	Chuck		Peterson
Bili Durham		Becky		Orvis
Sql Strlkes Back	Becky		Orvis
Price Kong		Carol		Delano
Hard Code		Carol		Delano

10 rows selected
----------------------------
#168
Jak widać, kolumna movie_title z tabeli Movies oraz kolumny person_fname, person_lname z tabeli People znajdujš się na jednym zestawieniu. Klauzula WHERE okrela drugi warunek wymagany przy złšczeniu tabel w zapytaniu. Zwykle najefektywniejsze połšczenia osišgamy poprzez kolumny będšce kluczami w łšczonych tabelach. Na przykład zawsze można dokonać połšczenia tabel, jeli klucz główny jednej tabeli jest kluczem obcym w drugiej.
===============
Rada
W przypadku, gdy łšczymy tabelę, w której klucz główny stanowi kilka kolumn, należy użyć wszystkich kolumn klucza przy okrelaniu warunków połšczenia. Aby uzyskać prawidłowe połšczenie takich tabel, musisz w klauzuli WHERE wpisać ten złożony warunek.
===================

Warunki złšczenia

Napisanie efektywnego zapytania łšczšcego wymaga podania odpowiednich warunków połšczenia. Zwykle okrela się je wewnštrz klauzuli WHERE. W przypadku łšczenia kilku tabel wymagane jest podanie wielu warunków.
Dla zapytania z listingu 8.3 warunek połšczenia okrelony jest przez wyrażenie director_id=person_id. Oznacza to, że jako wynik zapytania będš wybierane te wiersze tabel, dla których zachodzi podana równoć.
Tabele nie muszš być otwarcie projektowane do konkretnych połšczeń. W przykładzie z listingu 8.3 tabele zostały połšczone w oparciu o relację klucza głównego i klucza obcego. Nie jest to jednak warunek konieczny do utworzenia złšczenia. Często bardziej interesujšce zestawienia można uzyskać poprzez relacje odkryte po utworzeniu bazy danych. Na przykład zapytanie z listingu 8.4 wybiera osoby żyjšce
w tym samym miecie, w którym mieci się jakie studio filmowe.
----------------------------
Listing 8.4. Zapytanie łšczšce, znajduje osoby mieszkajšce w miastach, w których jest studio filmowe

SELECT person_fname, person_lnarae, studio_name
FROM  People, Studios
WHERE person_state  -  studio_state
AND person_city -  studio_city
----------------------------

Wartoci null nigdy nie sš traktowane jako spełniajšce warunek złšczenia. Wiersze, dla których w obu kolumnach łšczšcych znajdujš się wartoci null sš pomijane w wyniku zapytania. Wynika to stšd, że null traktowane sš jak wartoci nieokrelone i w zwišzku z tym, nie mogš być rozważane w kategorii równy, większy lub mniejszy.

Używanie złšczeń

Istnieje wiele zasad składniowych i innych technik zwišzanych z łšczeniem tabel. Wiele z nich wykorzystujemy w praktyce podczas tworzenia zapytań na podstawie kolumn z różnych tabel.
#169
Na przykład kiedy łšczone kolumny z różnych tabel majš takie same nazwy, to nazwę kolumny powinnimy poprzedzić nazwš tabeli, z której pochodzi kolumna i kropkš. Na listingu 8.5 pokazano dostosowany do tej konwencji zapis zapytania z listingu 8.3.
----------------------------
Listing 8.5. Zapytanie w notacji tabela.kolumna

SELECT Movies.movie_title,
People.person_fname, People .person_lname
FROM Movies, People
WHERE Movies.director_id - People.person_id

MOVIE_TITLE		PERSON_FNAME	PERSON_LNAME
----------------------------
Minerał House		Jeff		Price
Condependence Day		Jeff     	Price
The Programmer		Jeff       	Price
The Rear Windows		Jeff		Price
The Code Warrior		Chuck		Peterson
The Linux Files		Chuck		Peterson
Bili Durham			Becky  	Orvis
Sql Strikes Back		Becky		Orvis
Price Kong			Carol 	Delano
Hard Code			Carol		Delano

10 rows selected
----------------------------

Jedyna różnica pomiędzy zapytaniami z listingów 8.3 i 8.5 polega na umieszczeniu przed nazwš kolumny nazwy odpowiedniej tabeli. Dopóki nazwy kolumn z obu tabel sš różne, taki zapis nie jest obowišzkowy. Jednak w przypadku złożonych zapytań warto przestrzegać tej zasady, nawet jeli nie jest to konieczne.

Wybieranie kolumn

Tworzšc zapytanie łšczšce kilka tabel rzadko wybieramy wszystkie kolumny przy pomocy symbolu *.Użycie tego symbolu powoduje, że wszystkie kolumny ze wszystkich tabel pojawiš się w zestawieniu wynikowym. Jak się pewnie domylasz, to z kolei obniża przejrzystoć wyników zapytania. Listing 8.6 przedstawia wynik zapytania wybierajšcego wszystkie kolumny z tabel.
----------------------------
Listing 8.6. Zapytanie łšczšce, które wybiera wszystkie kolumny ...
Zgłoś jeśli naruszono regulamin