#189 Rozdział 9. Podzapytania W niektórych wypadkach najprostszš metodš osišgnięcia jakiego celu w języku SQL jest wykorzystanie wyniku jednego zapytania w drugim. Zagnieżdżone zapytania, nazywane również podzapytaniami, mogš być używane w klauzuli WHERE do filtrowania danych lub w instrukcji INSERT do kopiowania danych z jednej tabeli do drugiej. Podzapytań używamy, gdy dane z pewnej tabeli sš potrzebne w innym zapytaniu. Podobnie jak możemy zagnieżdżać wywołania funkcji w innych funkcjach, tak samo możemy zagnieżdżać zapytania w innych zapytaniach. Wykorzystujšc podzapytania można osišgnšć podobny efekt, jaki osišgamy przez wprowadzenie zmiennych w proceduralnych językach programowania. Zamiast wykonania instrukcji i przechowania j ej w zmiennej, wykonywane jest drugie wyrażenie wykorzystujšce poprzedni wynik, co daje efekt zagnieżdżania pierwszej instrukcji w drugiej. Podzapytania sš złożonš kwestiš z kilku powodów. Po pierwsze, wyróżniamy dwa zasadniczo różnišce się typy podzapytań. Po drugie, podzapytania mogš być wykorzystane w kilku typach instrukcji języka SQL. Po trzecie, wykorzystanie podzapytań zależy od typów danych zwracanych przez te zapytania. Przed zagłębieniem się w tematykę podzapytań, wypadałoby jeszcze dodać, że częć możliwoci podzapytań może być zastšpiona przez zapytania złšczajšce. Gdziekolwiek w tym rozdziale wprowadzę nowy typ podzapytania, pokażę również, jak je zastšpić (jeli to możliwe) przez złšczenie. Za każdym razem kiedy będzie to możliwe pokażę alternatywne wykorzystanie zapytań złšczajšcych, choć w przypadku najbardziej przydatnych podzapytań, nie ma możliwoci zastšpienia ich innymi metodami. ================== Rada Ze względu na uproszczenie przykładowej bazy danych, dane, którymi dysponuję, nie zawsze pozwalajš mi zademonstrować podzapytania w taki sposób, żeby pokazać, że jest to najlepsza metoda wyszukania odpowiednich danych. Mimo to wyjanię sytuacje, w których podzapytania sš najbardziej odpowiedniš technikš wyszukania potrzebnych danych. ===================== #190 Co to jest podzapytanie? Podzapytanie to, najprociej mówišc, instrukcja SELECT zagnieżdżona w innej instrukcji SQL, która dostarcza dla tej drugiej danych wejciowych. Podczas dyskusji o podzapytaniach będę odwoływał się do zapytań zewnętrznych jako otaczajšcych podzapytanie. Podzapytanie jest zapytaniem zagnieżdżonym. Zapytanie otaczajšce też może być podzapytaniem, ponieważ SQL nie wprowadza ograniczeń na iloć zagnieżdżeń. Jeli zapytanie jest podzapytaniem, to kolejne zapytanie może pojawić się w jego klauzuli WHERE. ================= Rada Niektórzy ludzie okrelajš zapytanie otaczajšce jako zapytanie zewnętrzne, a zapytanie zagnieżdżone jako wewnętrzne. ================ Rozpocznijmy od przykładu. Listing 9.1 zawiera przykład prezentowany już w rozdziale 6. "Zastosowanie klauzuli WHERE", gdzie wspomniałem, że podzapytania często pojawiajš się łšcznie z wyrażeniem IN. --------------------------- Listing 9.1. Podzapytanie w wyrażeniu IN SELECT movie_title, dlrector_id FROM Movies WHERE director_ld IN( SELECT person_id FROM People WHERE person_state = 'TX' ) MOVIE_TITLE STUDIO_ID --------------------------- Prince Kong 2 Hard Code 4 --------------------------- Zapytanie wewnętrzne na listingu 9.1 dostarcza listę wartoci z pola person_id do wyrażenia IN w zapytaniu otaczajšcym. Gdyby nie istniały podzapytania, to zapy- tanie musiałoby być zastšpione przez dwa oddzielne zapytania, jak pokazano na listingu 9.2 i 9.3. --------------------------- Listing 9.2. Pobranie listy osób z Teksasu SELECT person_id FROM People WHERE person_state = 'TX' PERSON_ID ------------- 4 5 6 10 --------------------------- #191 --------------------------- Listing 9.3. Wyszukanie listy filmów reżyserowanych przez osoby zamieszkałe w stanie Teksas SELECT movie_title, director_id FROM Movies WHERE director id IN(4, 5, 6,10) MOVIE_TITLE STUDIO_ID --------------------------- Prince Kong 2 Hard Code 4 --------------------------- Jeli nie zastosujemy podzapytania, to dane zwrócone przez zapytanie z listingu 9.2 muszš być wprowadzone do zapytania z listingu 9.3. Jak widać, możliwoć zagnieżdżania zapytań znacznie ułatwia uzyskiwanie potrzebnych informacji za pomocš tylko jednego zapytania. Zastępowanie podzapytań przez złšczenia Zapytanie z listingu 9. l może być również zastšpione przez złšczenie, jak pokazano na listingu 9.4. --------------------------- Listing 9.4. Złšczenie zastępujšce podzapytanie SELECT movie_title, studio_id FROM Movies, People WHERE diredctor_id=person_id AND person_state='TX' MOVIE_TITLE STUDIO_ID --------------------------- Prince Kong 2 Hard Code 4 --------------------------- Wyniki zapytań z listingów 9.4 i 9.1 sš identyczne. Nie ma żadnej przyczyny, dla której jedno z nich można by uznać za lepsze od drugiego. Sš porównywalne zarówno ze względu na wydajnoć jak i na wyniki. Wybór metody zależy od naszych upodobań. Typy podzapytań Wyróżniamy dwa typy podzapytań: powišzane i niepowišzane. Podzapytanie powišzane wymaga danych z zapytania otaczajšcego, zanim może być wykonane. Podzapytanie wykonuje się wykorzystujšc dane z zapytania otaczajšcego, a dane przez nie zwrócone sš z powrotem wprowadzane do zapytania otaczajšcego. Podzapytanie niepowišzane wykonuje się przed zapytaniem otaczajšcym, a jego wyniki sš przekazywane do zapytania otaczajšcego. Podzapytanie niepowišzane jest prostszym przykładem podzapytań, choć niekoniecznie częciej używanym. Podzapytania mogš być również wykorzystane w instrukcjach INSERT, aby dostarczyć wiersze z wartociami, które maja być wprowadzone do tabeli. Ponadto, podzapytania mogš być wykorzystane przez instrukcje UPDATE i DELETE do utworzenia złożonych warunków, niemożliwych do sformułowania za pomocš złšczeń. #192 Podzapytania niepowišzane Zapytanie wykorzystujšce niepowišzane podzapytanie, wykonuje zagnieżdżone zapytanie, wprowadza dane do zapytania otaczajšcego i wykonuje je. Podzapytanie niepowišzane można poznać po tym, że nie zawiera żadnych odwołań do zapytania otaczajšcego. Listing 9.1 zawiera przykład takiego powišzania. Poniżej przedstawiono ogólnš składnię takiego zapytania: SELECT select_listopad FROM table [ , table ...].. WHERE column_name IN (SELECT [DISTINC] column FROM table [WHERE condition]) Podzapytania niepowišzane mogš być pisane na wiele sposobów, ale najpopularniejsze jest użycie klauzuli IN. Na listingu 9.1 podzapytanie wybiera listę identyfikatorów z tabeli People, która jest wykorzystana jako lista wartoci w klauzuli IN. Takie zapytanie jest okrelane jako niepowišzane, ponieważ w żaden sposób nie zależy od otaczajšcego je zapytania.. Podzapytanie jest wykonywane, a wyniki sš porównywane z wartociami z tabeli okrelonej w zapytaniu otaczajšcym. Jak niedługo wyjanię, podzapytanie powišzane wykorzystuje dane wybrane przez zapytanie otaczajšce i dostarcza wyniki oparte na tych danych. Podzapytanie powišzane Zapytanie powišzane różni się od zapytania niepowišzanego tym, że pozycje z listy SELECT zapytania otaczajšcego sš wykorzystane wewnštrz klauzuli WHERE podza-pytania. Najprociej wyjanić to na przykładzie. Zapytanie powišzane przypomina złšczenia, ponieważ zawartoć tabeli występujšcej w podzapytaniu będzie porównywana z zawartociš tabeli z zapytania otaczajšcego, podobnie jak w zapytaniu złšczajšcym. Różnica polega na tym, że zamiast warunku złšczajšcego, powišzane podzapytanie odwołuje się do zapytania zewnętrznego przez klauzulę WHERE zapytania wewnętrznego. Ilustruje to listing 9.5. --------------------------- Listing 9.5. Powišzane podzapytanie SELECT person_fname, person_lname FROM People Pl WHERE 'Pam Green1 IN ( Select ROLE FROM Cast_movies WHERE Pl.person_id = cast_member_id) PERSON_FNAME PERSON_LNAME --------------------------- Carol Delano --------------------------- #193 Przedstawione zapytanie przetwarza każdy wiersz z tabeli People następujšco: 1. Zawartoć wiersza jest odczytywana z bazy danych. 2. Wykonuje się podzapytanie, a wartoci z aktualnie wybranego wiersza zapytania otaczajšcego sš wykorzystywane w klauzuli WHERE podzapytania. 3. Wyniki podzapytania sš przekazywane do klauzuli WHERE. 4. W przypadku, gdy wyrażenie logiczne w warunku klauzuli WHERE ma wartoć prawda, wiersz jest pobierany do zestawienia wynikowego, w przeciwnym wypadku jest pomijany. Funkcje zapytania z listingu 9.5 można zastšpić zapytaniem złšczajšcym, jak pokazuje to listing 9.6. --------------------------- Listing 9.6. Zapytanie złšczajšce zastępujšce poprzednie zapytanie SELECT person_fname, person_lname FROM People, Cast_Movies WHERE 'cast_member_id=person_id AND role ='Pam Green' PERSON_FNAME PERSON_LNAME --------------------------- Carol Delano --------------------------- Zdarzajš się również zadania, jak pokażę póniej, które mogš być zrealizowane tylko przez podzapytania. Podzapytania zwracajšce listę wartoci Podzapytania mogš być wykorzystywane w dwóch różnych kontekstach: kiedy wymagana jest pojedyncza wartoć lub kiedy wymagana jest lista wartoci. W przypadku, gdy wymagana jest lista wartoci, podzapytanie może zwrócić dowolnš liczbę wartoci (włšczajšc 0), zapewniajšc poprawne działanie zapytania. ================= Uwaga Podzapytanie użyte wewnštrz klauzuli WHERE musi zawsze zwrócić wartoci z jednej kolumny. Jeli wybierzemy wiele kolumn, pojawi się komunikat o błędzie. ===========...
Kwasibor666