POWTÓRZENIE Kontrola integralności danych; dane wymagane; więzy dziedzinowe; integralność encji; integralność referencyjna (związków); więzy ogólne. Zapytania SELECT; Funkcje agregujące; Przykłady.
Podzapytania - zapytania SELECT umieszczone w innym zapytaniu SELECT 2. Podzapytanie z równością – podaj wszystkich pracowników zatrudnionych w biurze przy ulicy Dobrej 22: SELECT personelNr, imie, nazwisko, stanowisko FROM personel WHERE biuroNr=(SELECT biuroNr FROM biuro WHERE ulica = 'Dobra 22');
mysql> SELECT personelNr, imie, nazwisko, stanowisko -> FROM personel -> WHERE biuroNr=(SELECT biuroNr -> FROM biuro WHERE ulica = 'Dobra 22'); +------------+--------+------------+------------+ | personelNr | imie | nazwisko | stanowisko | | SL30 | Jan | Wiśniewski | dyrektor | | SL31 | Julia | Lisicka | asystent | | SL32 | Michał | Brzęczyk | asystent | 3 rows in set (0.01 sec)
3. Podzapytanie z funkcją agregującą – podaj wszystkich 3. Podzapytanie z funkcją agregującą – podaj wszystkich pracowników, których pensja jest wyższa od średniej; pokaż różnice między poszczególnymi pensjami a średnią: SELECT personelNr, imie, nazwisko, stanowisko, pensja, pensja-(SELECT AVG(pensja)FROM personel) AS roznica FROM personel WHERE pensja>(SELECT AVG(pensja) FROM personel) ORDER BY pensja;
mysql> SELECT personelNr, imie, nazwisko, stanowisko, pensja, -> pensja-(SELECT AVG(pensja)FROM personel) AS roznica -> FROM personel -> WHERE pensja>(SELECT AVG(pensja) FROM personel) -> ORDER BY pensja; +------------+-----------+------------+------------+--------+-----------+ | personelNr | imie | nazwisko | stanowisko | pensja | roznica | | SA8 | Katarzyna | Morawska | kierownik | 1700 | 182.3529 | | SB21 | Daniel | Frankowski | kierownik | 1800 | 282.3529 | | SG20 | Karolina | Mucha | dyrektor | 2200 | 682.3529 | | SB20 | Sabina | Bober | dyrektor | 2400 | 882.3529 | | SB30 | Katarzyna | Michalska | dyrektor | 2500 | 982.3529 | | SL30 | Jan | Wiśniewski | dyrektor | 3000 | 1482.3529 | 6 rows in set (0.06 sec) mysql> SELECT AVG(pensja) FROM personel; +-------------+ | AVG(pensja) | | 1517.6471 | 1 row in set (0.00 sec)
4a. Podzapytania zagnieżdżone - powtórzenia właścicieli nieruchomości: SELECT wlascicielNr, nieruchomoscNr, miasto, ulica FROM nieruchomosc WHERE wlascicielNr IN (SELECT wlascicielNr FROM nieruchomosc GROUP BY wlascicielNr HAVING Count(*)>1 ) ORDER BY wlascicielNr;
mysql> SELECT wlascicielNr, nieruchomoscNr, miasto, ulica -> FROM nieruchomosc -> WHERE wlascicielNr IN (SELECT wlascicielNr FROM nieruchomosc -> GROUP BY wlascicielNr HAVING Count(*)>1 ) -> ORDER BY wlascicielNr; +--------------+----------------+-----------+------------+ | wlascicielNr | nieruchomoscNr | miasto | ulica | | CO87 | B21 | Białystok | Dobra 18 | | CO87 | L94 | Łomża | Akacjowa 6 | | CO93 | B16 | Białystok | Nowa 5 | | CO93 | B17 | Białystok | Mała 2 | 4 rows in set (0.06 sec)
4b. Podzapytania zagnieżdżone podwójnie - podaj wszystkie nieruchomości nadzorowane przez pracowników zatrudnionych w biurze przy ulicy Małej 63: SELECT nieruchomoscNr, miasto, ulica FROM nieruchomosc WHERE personelNr IN (SELECT personelNr FROM personel WHERE biuroNr = (SELECT biuroNr FROM biuro WHERE ulica = 'Mała 63'));
mysql> SELECT nieruchomoscNr, miasto, ulica -> FROM nieruchomosc -> WHERE personelNr IN (SELECT personelNr FROM personel -> WHERE biuroNr = (SELECT biuroNr FROM biuro WHERE -> ulica = 'Mała 63')); +----------------+-----------+----------+ | nieruchomoscNr | miasto | ulica | | B16 | Białystok | Nowa 5 | | B17 | Białystok | Mała 2 | | B18 | Białystok | Leśna 6 | | B21 | Białystok | Dobra 18 | 4 rows in set (0.01 sec)
5. Zastosowanie ANY / SOME - znajdź wszystkich pracowników, którzy mają pensję wyższą niż przynajmniej jeden pracownik biura o numerze B003 SELECT personelNr, imie, nazwisko, stanowisko, pensja FROM personel WHERE pensja > ANY (SELECT pensja FROM personel WHERE biuroNr='B003');
mysql> SELECT personelNr, imie, nazwisko, stanowisko, pensja -> FROM personel -> WHERE pensja > SOME (SELECT pensja FROM personel WHERE biuroNr='B003'); +------------+------------+------------+------------+--------+ | personelNr | imie | nazwisko | stanowisko | pensja | | SA8 | Katarzyna | Morawska | kierownik | 1700 | | SB20 | Sabina | Bober | dyrektor | 2400 | | SB21 | Daniel | Frankowski | kierownik | 1800 | | SB23 | Anna | Biały | asystent | 1200 | | SB30 | Katarzyna | Michalska | dyrektor | 2500 | | SB31 | Dawid | Piotrowski | asystent | 1100 | | SB32 | Małgorzata | Plichta | asystent | 1200 | | SG20 | Karolina | Mucha | dyrektor | 2200 | | SG21 | Piotr | Cybulski | asystent | 1300 | | SL20 | Paweł | Nowak | kierownik | 1500 | | SL22 | Monika | Munk | asystent | 1100 | | SL30 | Jan | Wiśniewski | dyrektor | 3000 | 12 rows in set (0.00 sec)
6. zastosowanie ALL - znajdź wszystkich pracowników, którzy mają pensję wyższą niż pensja każdego z pracowników biura o numerze B003 SELECT personelNr, imie, nazwisko, stanowisko, pensja FROM personel WHERE pensja > ALL (SELECT pensja FROM personel WHERE biuroNr='B003');
mysql> SELECT personelNr, imie, nazwisko, stanowisko, pensja -> FROM personel -> WHERE pensja > ALL (SELECT pensja FROM personel WHERE biuroNr='B003'); +------------+-----------+------------+------------+--------+ | personelNr | imie | nazwisko | stanowisko | pensja | | SB30 | Katarzyna | Michalska | dyrektor | 2500 | | SL30 | Jan | Wiśniewski | dyrektor | 3000 | 2 rows in set (0.04 sec)
Pracownicy biura B003 i ich zarobki: mysql> SELECT personelNr, imie, nazwisko, pensja -> FROM personel WHERE biuroNr = 'B003' -> ORDER BY pensja DESC; +------------+------------+------------+--------+ | personelNr | imie | nazwisko | pensja | | SB20 | Sabina | Bober | 2400 | | SB21 | Daniel | Frankowski | 1800 | | SB23 | Anna | Biały | 1200 | | SB22 | Małgorzata | Kowalska | 1000 | 4 rows in set (0.00 sec)
Wszyscy pracownicy biur i ich zarobki: mysql> SELECT personelNr, imie, nazwisko, pensja, biuroNr -> FROM personel ORDER BY pensja DESC; +------------+------------+------------+--------+---------+ | personelNr | imie | nazwisko | pensja | biuroNr | | SL30 | Jan | Wiśniewski | 3000 | B005 | | SB30 | Katarzyna | Michalska | 2500 | B006 | | SB20 | Sabina | Bober | 2400 | B003 | | SG20 | Karolina | Mucha | 2200 | B004 | | SB21 | Daniel | Frankowski | 1800 | B003 | | SA8 | Katarzyna | Morawska | 1700 | B007 | | SL20 | Paweł | Nowak | 1500 | B002 | | SG21 | Piotr | Cybulski | 1300 | B004 | | SB32 | Małgorzata | Plichta | 1200 | B006 | | SB23 | Anna | Biały | 1200 | B003 | | SB31 | Dawid | Piotrowski | 1100 | B006 | | SL22 | Monika | Munk | 1100 | B002 | | SB22 | Małgorzata | Kowalska | 1000 | B003 | | SL21 | Paweł | Kowalski | 1000 | B002 | | SL32 | Michał | Brzęczyk | 1000 | B005 | | SA9 | Maria | Hojna | 900 | B007 | | SL31 | Julia | Lisicka | 900 | B005 | 17 rows in set (0.00 sec)
Zapytania dotyczące wielu tabel
Proste złączenie dwóch tabel SELECT k.klientNr, imie, nazwisko, nieruchomoscNr, uwagi FROM klient k, wizyta w WHERE k.klientNr = w.klientNr; mysql> SELECT k.klientNr, imie, nazwisko, nieruchomoscNr, uwagi -> FROM klient k, wizyta w -> WHERE k.klientNr = w.klientNr; +----------+--------+------------+----------------+--------------+ | klientNr | imie | nazwisko | nieruchomoscNr | uwagi | | CR51 | Michał | Rafalski | A14 | za mały | | CR51 | Michał | Rafalski | B4 | brak jadalni | | CR52 | Ludwik | Wierzba | A14 | brak jadalni | | CR52 | Ludwik | Wierzba | B36 | NULL | | CR52 | Ludwik | Wierzba | B4 | NULL | | CR53 | Janusz | Kalinowski | B4 | za daleko | 6 rows in set (0.03 sec) Dla każdej z tabel wymienionych w klauzuli FROM można zdefiniować nazwę zastępczą - alias.
Złączenia tabel: Instrukcja SELECT o postaci: SELECT wyrażenie1, wyrażenie2, ... FROM tabela1, tabela2, ... zwraca tabelę o kolumnach zawierających wartości podanych wyrażeń, obliczone dla iloczynu kartezjańskiego (pełnego złączenia) podanych tabel.
Iloczyn kartezjański SELECT k.klientNr, imie, nazwisko, nieruchomoscNr, uwagi FROM klient k, wizyta w; mysql> SELECT k.klientNr, imie, nazwisko, nieruchomoscNr, uwagi -> FROM klient k, wizyta w; +----------+-----------+-------------+----------------+--------------+ | klientNr | imie | nazwisko | nieruchomoscNr | uwagi | | CO16 | Alicja | Stefańska | A14 | za mały | | CO16 | Alicja | Stefańska | B4 | brak jadalni | | CO16 | Alicja | Stefańska | A14 | brak jadalni | | CO16 | Alicja | Stefańska | B36 | NULL | | CO16 | Alicja | Stefańska | B4 | NULL | | CO16 | Alicja | Stefańska | B4 | za daleko | | CO17 | Katarzyna | Winiarska | A14 | za mały | | CO17 | Katarzyna | Winiarska | B4 | brak jadalni | | CO17 | Katarzyna | Winiarska | A14 | brak jadalni | | CO17 | Katarzyna | Winiarska | B36 | NULL | | CO17 | Katarzyna | Winiarska | B4 | NULL | | CO17 | Katarzyna | Winiarska | B4 | za daleko | | CO18 | Anna | Nowak | A14 | za mały | | CO18 | Anna | Nowak | B4 | brak jadalni | | CO18 | Anna | Nowak | A14 | brak jadalni | ...
| CO18 | Anna | Nowak | B36 | NULL | | CO18 | Anna | Nowak | B4 | za daleko | | CR51 | Michał | Rafalski | A14 | za mały | | CR51 | Michał | Rafalski | B4 | brak jadalni | | CR51 | Michał | Rafalski | A14 | brak jadalni | | CR51 | Michał | Rafalski | B36 | NULL | | CR51 | Michał | Rafalski | B4 | NULL | | CR51 | Michał | Rafalski | B4 | za daleko | | CR52 | Ludwik | Wierzba | A14 | za mały | | CR52 | Ludwik | Wierzba | B4 | brak jadalni | | CR52 | Ludwik | Wierzba | A14 | brak jadalni | | CR52 | Ludwik | Wierzba | B36 | NULL | | CR52 | Ludwik | Wierzba | B4 | NULL | | CR52 | Ludwik | Wierzba | B4 | za daleko | | CR53 | Janusz | Kalinowski | A14 | za mały | | CR53 | Janusz | Kalinowski | B4 | brak jadalni | | CR53 | Janusz | Kalinowski | A14 | brak jadalni | | CR53 | Janusz | Kalinowski | B36 | NULL | | CR53 | Janusz | Kalinowski | B4 | NULL | | CR53 | Janusz | Kalinowski | B4 | za daleko | | CR54 | Maria | Tomaszewska | A14 | za mały | | CR54 | Maria | Tomaszewska | B4 | brak jadalni | | CR54 | Maria | Tomaszewska | A14 | brak jadalni | | CR54 | Maria | Tomaszewska | B36 | NULL | | CR54 | Maria | Tomaszewska | B4 | NULL | | CR54 | Maria | Tomaszewska | B4 | za daleko | +----------+-----------+-------------+----------------+--------------+ 42 rows in set (0.00 sec)
Najczęściej bardziej przydatne są zapytania wykorzystujące równozłączenia tabel, a nie iloczyny kartezjańskie. Dokonuje się tego za pomocą odpowiednio dobranego warunku w klauzuli WHERE: SELECT wyrażenie1, wyrażenie2, ... FROM tabela1, tabela2, ... WHERE warunek Notacje: tabela1, tabela2 tabela1 JOIN tabela2 są równoważne. Warunek w klauzuli WHERE powinien być wyrażeniem logicznym dotyczącym kolumn złączanych tabel, dyktuje on które wiersze iloczynu kartezjańskiego zostaną uwzględnione w złączeniu.
Inny sposób złączenia tabel to złączenie zewnętrzne. MySQL implementuje dwie postacie zapisu lewostronnego złączenia zewnętrznego: tabela1 LEFT [OUTER] JOIN tabela2 ON warunek gdzie warunek po słowie kluczowym ON może być dowolnym wyrażeniem logicznym zbudowanym z wykorzystaniem nazw kolumn złączanych tabel. Oraz druga postać: USING (kolumna1, kolumna2, ...)
Lista nazw kolumn po słowie kluczowym USING musi zawierać kolumny występujące w obu złączanych tabelach pod tymi samymi nazwami. Inaczej mówiąc, notacja powyższa jest równoważna zapisowi tabela1 LEFT [OUTER] JOIN tabela2 ON tabela1.kolumna1=tabela2.kolumna1 AND tabela1.kolumna2=tabela2.kolumna2 ... Słowo kluczowe OUTER jest opcjonalne i nie ma wpływu na efekt złączenia.
Definicja (lewostronnego) złączenia zewnętrznego oznacza, że jeżeli w ,,prawej'' tabeli brak wiersza ,,pasującego'' do pewnego wiersza tabeli ,,lewej'' (tzn. spełniającego warunek złączenia), to stworzony zostanie wiersz zawierający wartość NULL we wszystkich kolumnach pochodzących z tabeli ,,prawej''. Dodatkowo istnieje jeszcze operacja naturalnego złączenia lewostronnego: tabela1 NATURAL LEFT [OUTER] JOIN tabela2 będąca po prostu skrótowym zapisem złączenia z klauzulą USING zawierającą jako argument listę nazw wszystkich kolumn powtarzających się w obu złączanych tabelach.
Złączenia Operacja złączenia kojarzy dane z dwóch tabel, tworząc pary z wierszy, w których kolumny złączenia mają taką samą wartość. Dla złączenia wewnętrznego – jeżeli wiersz tabeli nie zostanie połączony w parę (z żadnym wierszem z drugiej tabeli), to nie trafia do tabeli wynikowej. Złączenie zewnętrzne zachowuje wiersze niespełniające warunku złączenia.
7. Złączenie wewnętrzne - podaj biura i nieruchomości znajdujące się w tym samym mieście: mysql> SELECT * FROM biuro2; +---------+-----------+ | biuronr | miasto | | B002 | Łomża | | B003 | Białystok | | B004 | Grajewo | mysql> SELECT * FROM nieruchomosc2; +---------------+-----------+ | nieruchomoscr | miasto | | A14 | Augustów | | B4 | Białystok | | L94 | Łomża | SELECT Biuro2.*, Nieruchomosc2.* FROM Biuro1 INNER JOIN Nieruchomosc2 ON Biuro2.miasto = Nieruchomosc2.miasto;
Polecenie równoważne: SELECT biuro2.*, nieruchomosc2.* mysql> SELECT biuro2.*, nieruchomosc2.* -> FROM biuro2 INNER JOIN nieruchomosc2 ON biuro2.miasto = nieruchomosc2.miasto; +---------+------------+----------------+------------+ | biuroNr | miasto | nieruchomoscNr | miasto | | B003 | Białystok | B4 | Białystok | | B002 | Łomża | L94 | Łomża | 2 rows in set (0.00 sec) Polecenie równoważne: SELECT biuro2.*, nieruchomosc2.* FROM biuro2 INNER JOIN nieruchomosc2 USING(miasto);
Przykład na innych tabelach: SELECT biuro.biuronr, biuro.miasto, personel.personelnr, personel.nazwisko, personel.biuronr FROM biuro INNER JOIN personel ON biuro.biuronr = personel.biuronr;
8. Lewostronne złączenie zewnętrzne: - podaj biura i nieruchomości znajdujące się w tym samym mieście, umieść również te biura, w których nie zarejestrowano żadnej nieruchomości: SELECT Biuro2.*, Nieruchomosc2.* FROM Biuro2 LEFT JOIN Nieruchomosc2 ON Biuro2.miasto = Nieruchomosc2.miasto; mysql> SELECT biuro2.*, nieruchomosc2.* -> FROM biuro2 LEFT JOIN nieruchomosc2 ON biuro2.miasto = nieruchomosc2.miasto; +---------+------------+----------------+------------+ | biuroNr | miasto | nieruchomoscNr | miasto | | B002 | Łomża | L94 | Łomża | | B003 | Białystok | B4 | Białystok | | B004 | Grajewo | NULL | NULL | 3 rows in set (0.02 sec)
SELECT biuro2.*, nieruchomosc2.* Z dodanymi warunkami: SELECT biuro2.*, nieruchomosc2.* FROM biuro2 LEFT JOIN nieruchomosc2 USING(miasto) WHERE nieruchomosc2.miasto IS NULL; mysql> SELECT biuro2.*, nieruchomosc2.* -> FROM biuro2 LEFT JOIN nieruchomosc2 USING(miasto) -> WHERE nieruchomosc2.miasto IS NULL; +---------+---------+----------------+--------+ | biuroNr | miasto | nieruchomoscNr | miasto | | B004 | Grajewo | NULL | NULL | 1 row in set (0.00 sec)
Przykład na innych tabelach: SELECT biuro.biuronr, biuro.miasto, personel.personelnr, personel.nazwisko, personel.biuronr FROM biuro LEFT JOIN personel ON biuro.biuronr = personel.biuronr;
9. Prawostronne złączenie zewnętrzne: - podaj biura i nieruchomości znajdujące się w tym samym mieście, umieść również nieruchomości nie zarejestrowane w żadnym biurze: SELECT biuro2.*, nieruchomosc2.* FROM biuro2 RIGHT JOIN nieruchomosc2 ON biuro2.miasto = nieruchomosc2.miasto; mysql> SELECT biuro2.*, nieruchomosc2.* -> FROM biuro2 RIGHT JOIN nieruchomosc2 ON biuro2.miasto = nieruchomosc2.miasto; +---------+------------+----------------+------------+ | biuroNr | miasto | nieruchomoscNr | miasto | | NULL | NULL | A14 | Augustów | | B003 | Białystok | B4 | Białystok | | B002 | Łomża | L94 | Łomża | 3 rows in set (0.00 sec)
SELECT biuro2.*, nieruchomosc2.* Z dodanymi warunkami: SELECT biuro2.*, nieruchomosc2.* FROM biuro2 LEFT JOIN nieruchomosc2 USING(miasto) WHERE biuro2.miasto IS NULL; mysql> SELECT biuro2.*, nieruchomosc2.* -> FROM biuro2 RIGHT JOIN nieruchomosc2 USING(miasto) -> WHERE biuro2.miasto IS NULL; +---------+--------+----------------+-----------+ | biuroNr | miasto | nieruchomoscNr | miasto | | NULL | NULL | A14 | Augustów | 1 row in set (0.01 sec)
Przykład na innych tabelach: SELECT biuro.biuronr, biuro.miasto, personel.personelnr, personel.nazwisko, personel.biuronr FROM biuro RIGHT JOIN personel ON biuro.biuronr = personel.biuronr; Wynik w tym przypadku identyczny jak dla INNER JOIN ze względu na istniejące więzy między tabelami
Pełne złączenie zewnętrzne - podaj biura i nieruchomości znajdujące się w tym samym mieście, umieść również te biura, w których nie zarejestrowano żadnej nieruchomości oraz nieruchomości nie zarejestrowane w żadnym biurze: SELECT Biuro2.*, Nieruchomosc2.* FROM Biuro1 FULL JOIN Nieruchomosc2 ON Biuro2.miasto = Nieruchomosc2.miasto;
Utworzenie pełnego złączenia zewnętrznego (z wykorzystaniem UNION): (SELECT biuro2.biuroNr, biuro2.miasto, nieruchomosc2.nieruchomoscNr, nieruchomosc2.miasto AS miasto2 FROM (biuro2 LEFT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto))) UNION FROM (biuro2 RIGHT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto)));
mysql> (SELECT biuro2.biuroNr, biuro2.miasto, nieruchomosc2.nieruchomoscNr, -> nieruchomosc2.miasto AS miasto2 -> FROM (biuro2 LEFT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto))) -> UNION -> (SELECT biuro2.biuroNr, biuro2.miasto, -> FROM (biuro2 RIGHT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto))); +---------+-----------+----------------+-----------+ | biuronr | miasto | nieruchomoscnr | miasto2 | | B002 | Łomża | L94 | Łomża | | B003 | Białystok | B4 | Białystok | | B004 | Grajewo | NULL | NULL | | NULL | NULL | A14 | Augustów | 4 rows in set (0.00 sec)
mysql> (SELECT biuro2.biuroNr, biuro2.miasto, nieruchomosc2.nieruchomoscNr, -> nieruchomosc2.miasto -> FROM (biuro2 LEFT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto))) -> UNION -> (SELECT biuro2.biuroNr, biuro2.miasto, -> FROM (biuro2 RIGHT JOIN nieruchomosc2 ON (biuro2.miasto = nieruchomosc2.miasto))); +---------+-----------+----------------+-----------+ | biuroNr | miasto | nieruchomoscNr | miasto | | B002 | Łomża | L94 | Łomża | | B003 | Białystok | B4 | Białystok | | B004 | Grajewo | NULL | NULL | | NULL | NULL | A14 | Augustów | 4 rows in set (0.00 sec)
UNION mysql> (SELECT nieruchomoscnr, miasto, personelnr FROM nieruchomosc WHERE biuronr='B003' AND personelnr='SB23') -> UNION -> (SELECT nieruchomoscnr, miasto, personelnr FROM nieruchomosc WHERE biuronr='B005' AND personelnr='SL31') -> ORDER BY nieruchomoscnr; +----------------+-----------+------------+ | nieruchomoscnr | miasto | personelnr | | B17 | Białystok | SB23 | | B18 | Białystok | SB23 | | L94 | Łomża | SL31 | 3 rows in set (0.11 sec)
LIMIT mysql> (SELECT nieruchomoscNr, miasto, personelNr FROM nieruchomosc WHERE biuroNr='B003' AND personelNr='SB23') -> UNION -> (SELECT nieruchomoscNr, miasto, personelNr FROM nieruchomosc WHERE biuroNr='B005' AND personelNr='SL31') -> ORDER BY nieruchomoscnr -> LIMIT 2; +----------------+-----------+------------+ | nieruchomoscnr | miasto | personelnr | | B17 | Białystok | SB23 | | B18 | Białystok | SB23 | 2 rows in set (0.09 sec)
LIMIT mysql> SELECT personelNr, imie, nazwisko, pensja, biuroNr -> FROM personel -> LIMIT 8; +------------+------------+------------+--------+---------+ | personelNr | imie | nazwisko | pensja | biuroNr | | SA8 | Katarzyna | Morawska | 1700 | B007 | | SA9 | Maria | Hojna | 900 | B007 | | SB20 | Sabina | Bober | 2400 | B003 | | SB21 | Daniel | Frankowski | 1800 | B003 | | SB22 | Małgorzata | Kowalska | 1000 | B003 | | SB23 | Anna | Biały | 1200 | B003 | | SB30 | Katarzyna | Michalska | 2500 | B006 | | SB31 | Dawid | Piotrowski | 1100 | B006 | 8 rows in set (0.00 sec)
Widoki (views) - Perspektywy: Perspektywa – dynamicznie obliczany wynik jednej lub wielu operacji relacyjnych tworzących nową relację (tabelę) z relacji bazowych. Perspektywa jest relacją wirtualną, która nie musi fizycznie istnieć w bazie danych, ale może być wyliczona w każdej chwili na żądanie użytkownika. Składnia polecenia: CREATE [OR REPLACE] VIEW nazwa_perspektywy [(lista_kolumn)] AS SELECT zapytanie [WITH [CASCADED | LOCAL] CHECK OPTION]
Jeżeli w poleceniu pominięta jest lista kolumn, to każda z kolumn perspektywy będzie miała taką samą nazwę, jak odpowiednia kolumna w wyniku zapytania SELECT. Lista kolumn powinna być podana, jeśli istnieją jakiekolwiek niejasności dotyczące nazw kolumn (np. dla kolumn wyliczanych lub, gdy w wyniku złączenia powstają dwie kolumny o identycznych nazwach).
Usuwanie perspektywy: DROP VIEW [IF EXISTS] nazwa_perspektywy [, nazwa_perspektywy] ... [RESTRICT | CASCADE] Modyfikowanie perspektywy: ALTER VIEW nazwa_perspektywy [(lista_kolumn)] AS SELECT zapytanie [WITH [CASCADED | LOCAL] CHECK OPTION]
Rodzaje perspektyw: Utworzenie perspektywy poziomej: mysql> CREATE VIEW _11_biuro_B003 AS SELECT personelNr, imie, nazwisko, stanowisko, pensja -> FROM personel WHERE biuronr='B003'; -> SELECT * FROM _11_biuro_B003; Query OK, 0 rows affected (0.02 sec) +------------+-------------+------------+------------+--------+ | personelNr | imie | nazwisko | stanowisko | pensja | | SB20 | Sabina | Bober | dyrektor | 2400 | | SB21 | Daniel | Frankowski | kierownik | 1800 | | SB22 | Małgorzata | Kowalska | asystent | 1000 | | SB23 | Anna | Biały | asystent | 1200 | 4 rows in set (0.01 sec)
Utworzenie perspektywy pionowej: mysql> CREATE VIEW _10_dyrektorzy AS SELECT personelnr, pensja -> FROM personel WHERE stanowisko='dyrektor'; -> SELECT * FROM _10_dyrektorzy; Query OK, 0 rows affected (0.03 sec) +------------+--------+ | personelnr | pensja | | SB20 | 2400 | | SB30 | 2500 | | SG20 | 2200 | | SL30 | 3000 | 4 rows in set (0.02 sec)
Perspektywy oparte na grupowaniu: mysql> CREATE VIEW srednie AS SELECT uczen, przedmiot, -> AVG(ocena) AS srednia FROM oceny -> GROUP BY uczen, przedmiot; -> SELECT* FROM srednie; +-------+------------+---------+ | uczen | przedmiot | srednia | | 1 | biologia | 5.00000 | | 1 | matematyka | 3.83333 | | 1 | polski | 4.00000 | | 2 | biologia | 3.25000 | | 2 | matematyka | 3.12500 | | 2 | polski | 4.66667 |
Podaj nieruchomości, które były wynajmowane częściej niż średnio: mysql> CREATE VIEW tmp AS SELECT count(nieruchomoscNr) AS ile FROM wynajecie w GROUP BY nieruchomoscNr; Query OK, 0 rows affected (0.04 sec) mysql> SELECT * FROM tmp; +-----+ | ile | | 3 | | 4 | | 2 | 7 rows in set (0.01 sec)
mysql> CREATE VIEW srednio AS SELECT n. nieruchomoscNr, miasto, n mysql> CREATE VIEW srednio AS SELECT n.nieruchomoscNr, miasto, n.czynsz, count(*) FROM nieruchomosc n, wynajecie w -> WHERE w.nieruchomoscNr = n.nieruchomoscNr -> GROUP BY nieruchomoscNr -> HAVING count(*)>=(SELECT AVG(ile) FROM tmp); Query OK, 0 rows affected (0.10 sec) mysql> SELECT * FROM srednio; +----------------+-----------+--------+----------+ | nieruchomoscNr | miasto | czynsz | count(*) | | A14 | Augustów | 715 | 3 | | B16 | Białystok | 495 | 4 | 2 rows in set (0.01 sec)
SELECT AVG(ile) AS srednia FROM (SELECT count(nieruchomoscNr) AS ile FROM wynajecie w GROUP BY nieruchomoscNr) tmp; mysql> SELECT AVG(ile) AS srednia FROM -> (SELECT count(nieruchomoscNr) AS ile -> FROM wynajecie w GROUP BY nieruchomoscNr) tmp; +---------+ | srednia | | 2.2857 | 1 row in set (0.00 sec)
Podaj nieruchomości, które były wynajmowane częściej niż średnio: SELECT n.nieruchomoscNr, miasto, n.czynsz, count(*) FROM nieruchomosc n, wynajecie w WHERE w.nieruchomoscNr = n.nieruchomoscNr GROUP BY nieruchomoscNr HAVING count(*)>=(SELECT AVG(ile) FROM (SELECT count(nieruchomoscNr) AS ile FROM wynajecie w GROUP BY nieruchomoscNr) tmp); +----------------+-----------+--------+----------+ | nieruchomoscNr | miasto | czynsz | count(*) | | A14 | Augustów | 715 | 3 | | B16 | Białystok | 495 | 4 |
bez WHERE mysql> SELECT n.nieruchomoscNr, miasto, n.czynsz, count(*) -> FROM nieruchomosc n, wynajecie w -> GROUP BY nieruchomoscNr -> HAVING count(*)>=(SELECT AVG(ile) FROM -> (SELECT count(nieruchomoscNr) AS ile -> FROM wynajecie w GROUP BY nieruchomoscNr) tmp); +----------------+-----------+--------+----------+ | nieruchomoscNr | miasto | czynsz | count(*) | | A14 | Augustów | 715 | 17 | | B16 | Białystok | 495 | 17 | | B17 | Białystok | 412 | 17 | | B18 | Białystok | 385 | 17 | | B21 | Białystok | 660 | 17 | | G01 | Grajewo | 830 | 17 | | L94 | Łomża | 440 | 17 | 7 rows in set (0.01 sec) Wszystkie 7 nieruchomości i wszystkie 17 wynajęć
Inne przykłady: mysql> CREATE TABLE test (ilosc INT, cena INT); Query OK, 0 rows affected (0.05 sec) mysql> INSERT INTO test VALUES(3, 50); Query OK, 1 row affected (0.00 sec) mysql> CREATE VIEW w AS SELECT ilosc, cena, ilosc*cena AS wartosc FROM test; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM w; +-------+------+---------+ | ilosc | cena | wartosc | | 3 | 50 | 150 | 1 row in set (0.00 sec)
mysql> CREATE VIEW roczna AS SELECT personelNr, stanowisko, pensja, pensja*12 AS pensja_roczna FROM personel; Query OK, 0 rows affected (0.02 sec) mysql> SELECT * FROM roczna; +------------+------------+--------+---------------+ | personelNr | stanowisko | pensja | pensja_roczna | | SA8 | kierownik | 1700 | 20400 | | SA9 | asystent | 900 | 10800 | | SB20 | dyrektor | 2400 | 28800 | | SB21 | kierownik | 1800 | 21600 | | SB22 | asystent | 1000 | 12000 | | SB23 | asystent | 1200 | 14400 | | SB30 | dyrektor | 2500 | 30000 | | SB31 | asystent | 1100 | 13200 | | SB32 | asystent | 1200 | 14400 | | SG20 | dyrektor | 2200 | 26400 | | SG21 | asystent | 1300 | 15600 | | SL20 | kierownik | 1500 | 18000 | | SL21 | asystent | 1000 | 12000 | | SL22 | asystent | 1100 | 13200 | | SL30 | dyrektor | 3000 | 36000 | | SL31 | asystent | 900 | 10800 | | SL32 | asystent | 1000 | 12000 | 17 rows in set (0.01 sec)
mysql> CREATE TABLE t1 (a INT); Query OK, 0 rows affected (0.19 sec) mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2 -> WITH CHECK OPTION; Query OK, 0 rows affected (0.08 sec) mysql> CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0 -> WITH LOCAL CHECK OPTION; Query OK, 0 rows affected (0.05 sec) mysql> CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0 -> WITH CASCADED CHECK OPTION; Query OK, 0 rows affected (0.02 sec) mysql> INSERT INTO v2 VALUES (2); Query OK, 1 row affected (0.06 sec) mysql> select * from t1; +------+ | a | | 2 | 1 row in set (0.00 sec)
mysql> select * from t1; +------+ | a | | 2 | 1 row in set (0.00 sec) mysql> INSERT INTO v1 VALUES (2); ERROR 1369 (HY000): CHECK OPTION failed 'biuro.v1' mysql> INSERT INTO v3 VALUES (2); ERROR 1369 (HY000): CHECK OPTION failed 'biuro.v3' mysql> INSERT INTO v1 VALUES (1); Query OK, 1 row affected (0.00 sec) | 1 | 2 rows in set (0.01 sec)
mysql> CREATE VIEW _10_dyrektorzy2 AS SELECT personelnr,nazwisko,imie,stanowisko, pensja,biuroNr FROM personel WHERE stanowisko='dyrektor' AND pensja >= 2500 WITH CHECK OPTION; SELECT * FROM _10_dyrektorzy2; Query OK, 0 rows affected (0.01 sec) +------------+------------+-----------+------------+--------+---------+ | personelnr | nazwisko | imie | stanowisko | pensja | biuroNr | | SB30 | Michalska | Katarzyna | dyrektor | 2500 | B006 | | SL30 | Wiśniewski | Jan | dyrektor | 3000 | B005 | 2 rows in set (0.00 sec) mysql> INSERT INTO _10_dyrektorzy2 (personelNr, nazwisko, imie, stanowisko, pensja, biuroNr) VALUES ('SA1 ','Biedak', 'Jan', 'dyrektor', 2000, 'B007 '); ERROR 1369 (HY000): CHECK OPTION failed 'gilg._10_dyrektorzy2' mysql> INSERT INTO _10_dyrektorzy2 (personelNr,nazwisko,imie,stanowisko,pensja, biuroNr) VALUES ('SC1 ','Bogacz', 'Jan', 'dyrektor', 5000, 'B001 '); Query OK, 1 row affected, 2 warnings (0.09 sec) mysql> SELECT * FROM _10_dyrektorzy2; | SC1 | Bogacz | Jan | dyrektor | 5000 | B001 | 3 rows in set (0.00 sec)