Wykład 6 SQL praca z tabelami 3
Łączenie wyników zapytań Język SQL zawiera mechanizmy pozwalające na łączenie wyników kilku pytań. Pozwalają na to instrukcje UNION, INTERSECT, EXCEPT o postaci: zapytanie1 UNION INTERSECT EXCEPT zapytanie2 [ UNION INTERSECT EXCEPT zapytanien] a zatem może służyć do łączenia dwóch lub większej liczby zapytań. W MySQL występuje tylko instrukcja UNION. Rozważmy bazy zawierające dwie tabele dla pracowników dwóch uczelni UczelniaA i UczelniaB o strukturze: CREATE TABLE UczelniaA UczelniaB ( id INTEGER PRIMARY KEY, imie VARCHAR(20) NOT NULL, nazwisko VARCHAR(30) NOT NULL, pesel CHAR(11) ); wypełnione danymi:
Łączenie wyników zapytań INSERT INTO UczelniaA VALUES (1, Jan, Kowalski, 01234567890 ); INSERT INTO UczelniaA VALUES (2, Adam, Nowak, 12345678901 ); INSERT INTO UczelniaA VALUES (3, Anna, Wilk, 23456789012 ); INSERT INTO UczelniaB VALUES (1, Janina, Wolska, 34567890123 ); INSERT INTO UczelniaB VALUES (2, Beata, Nowak, 45678901234 ); INSERT INTO UczelniaB VALUES (3, Jan, Kowalski, 01234567890 ); Instrukcja UNION: zapytanie1 UNION [ALL] zapytanie2 [ UNION zapytanien] Łączy wyniki zapytań zapytanie1 i zapytanie2 (ewentualnie następnych). Oba zapytania muszą zwracać taką samą liczbę kolumn o takich samych typach. Z klauzulą ALL w wynikach uwzględniane są wszystkie wiersze z obu zapytań. Bez klauzuli ALL w wynikach zostają pominięte duplikaty danych (tak jak przy użyciu słowa DISTINCT).
Łączenie wyników zapytań Przykład: SELECT imię, nazwisko, pesel FROM UczelniaA UNION SELECT imię, nazwisko, pesel FROM UczelniaB; wyświetli trzy kolumny, a w wynikach wiersz Jan Kowalski pojawi się jedynie raz (z klauzula ALL Jan Kowalski pojawi się dwukrotnie). Instrukcje INTERSECT, EXCEPT wyglądają podobnie i nie występują w większości wersji MySQL
Pobieranie danych z wielu tabel Instrukcja SELECT pozwala również na pobieranie danych z wielu tabel: w postaci FROM tabela1, tabela2,, tabelan [WHERE warunki] [ORDER BY kolumna1, kolumna2,, kolumnan [ASC DESC] ] przykładowo z tabel: CREATE TABLE pracownicy CREATE TABLE stanowiska ( ( id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY, imie VARCHAR(20) NOT NULL, nazwa VARCHAR(20) NOT NULL nazwisko VARCHAR(30) NOT NULL, ); placa DECIMAL(7,2) NOT NULL, stanowisko_id INTEGER, pesel CHAR(11) );
Pobieranie danych z wielu tabel Instrukcja SELECT dla tych dwóch tabel w postaci: SELECT imie, nazwisko, nazwa, placa FROM pracownicy, stanowiska; jest bardzo niepraktyczna, bo w wynikach zostaje złączony każdy wiersz tabeli pracownicy z każdym wierszem w tabeli stanowiska czyli uzyskamy iloczyn kartezjański obu tabel. Należałoby dodać warunek wiążący pracowników z zajmowanymi stanowiskami (czyli id z tabeli stanowiska ze stanowsko_id w tabeli pracownicy) : SELECT imie, nazwisko, nazwa, placa FROM pracownicy, stanowiska WHERE pracownicy.stanowisko_id = stanowiska.id; który wyświetli wszystkich pracowników wraz z zajmowanymi przez nich stanowiskami. Dodanie na końcu instrukcji ORDER BY pozwala na sortowanie wyników (np. ORDER BY placa DESC )
Pobieranie danych z wielu tabel - Złączenia Jeśli pobieramy dane z więcej niż jednej tabeli to w rzeczywistosci wykonujemy tak zwane złączenie. W języku SQL istnieją dedykowane instrukcje pozwalające na formalne wykonanie złączenia tabel. Najczęściej stosowane to : - CROSS JOIN - INNER JOIN - LEFT OUTER JOIN - RIGHT OUTER JOIN - FULL OUTER JOIN CROSS JOIN (złącze krzyżowe) postaci: FROM tabela1 CROSS JOIN tabela2 wykonuje iloczyn kartezjański łączonych tabel, czyli łączy każdy wiersz tabela1 z każdym wierszem tabeli tabela2 i jest odpowiednikiem instrukcji: FROM tabela1, tabela2
Złączenia INNER JOIN (złącze warunkowe ) postaci: FROM tabela1 INNER JOIN tabela2 ON wyrażenie warunkowe w wyniku pojawiają się tylko te wiersze z tabel tabela1 i tabela2, które spełniają warunki wymienione po klauzuli ON. Jest to odpowiednik instrukcji: FROM tabela1, tabela2,, tabelan WHERE warunki
Złączenia LEFT OUTER JOIN postaci: FROM tabela1 LEFT OUTER JOIN tabela2 ON wyrażenie warunkowe pozwala na uwzględnienie w wynikach danych, które nie maja swoich odpowiedników w złączanych tabelach. Zatem jeżeli w tabela1 znajdują się wiersze, które nie mają swoich odpowiedników w tabela2 to i tak zostaną one uwzględnione w wynikach, a w miejsce pustych kolumn pojawi się NULL, np. SELECT imię, nazwisko, nazwa, placa FROM pracownicy LEFT OUTER JOIN stanowiska ON pracownicy.stanowisko_id = stanowiska.id; Złączenie tego typu pozwala na wykrycie problemów/nadmiarowości w konfiguracji w bazie danych (np. stanowiska nie przypisanego do pracownika) lub braku danych w bazie.
Złączenia RIGHT OUTER JOIN postaci: FROM tabela1 RIGHT OUTER JOIN tabela2 ON wyrażenie warunkowe pozwala na uwzględnienie w wynikach danych, które nie maja swoich odpowiedników w złączanych tabelach. W przeciwieństwie do LEFT OUTER JOIN tutaj jeżeli w tabela2 znajdują się wiersze, które nie mają swoich odpowiedników w tabela1 to i tak zostaną one uwzględnione w wynikach, a w miejsce pustych kolumn pojawi się NULL, np. SELECT imię, nazwisko, nazwa, placa FROM pracownicy RIGHT OUTER JOIN stanowiska ON pracownicy.stanowisko_id = stanowiska.id; Złączenie tego typu pozwala na wykrycie problemów/nadmiarowości w konfiguracji w bazie danych (np. brak pracownika przypisanego do jakiegoś stanowiska) lub braku danych w bazie. Złącza LEFT OUTER JOIN i RIGHT OUTER JOIN są zamienne, wystarczy zamienić kolejność tabel podanych w poleceniu.
Złączenia FULL OUTER JOIN postaci: FROM tabela1 FULL OUTER JOIN tabela2 ON wyrażenie warunkowe jest połączeniem LEFT OUTER JOIN, RIGHT OUTER JOIN i wykrywa oba typy braków odpowiedników. FULL OUTER JOIN występuje nie we wszystkich wersjach SQL. Złączenie z dodatkowym warunkiem. Do złączenia można wprowadzić dodatkowy warunek poprzez klauzulę WHERE. Wówczas najpierw wykonywane jest złączenie zgodnie z wymogiem warunkowym po słowie ON, później sprawdzany jest dodatkowy warunek występujący po klauzuli WHERE np. SELECT imię, nazwisko, nazwa, placa FROM pracownicy FULL OUTER JOIN stanowiska ON pracownicy. stanowisko_id = stanowiska.id WHERE nazwa is NULL; Przykład wyświetla tylko pracowników bez przypisanego (lub źle przypisanego) stanowiska.