Grupowania i podzapytania
Transkrypt
Grupowania i podzapytania
Grupowanie i funkcje agregujące Zadanie 1. Stwórz odpowiednią tabelę Test_agr i wprowadź odpowiednie rekordy tak, aby wynik zapytania SELECT AVG(kol) avg_all, AVG(DISTINCT kol) avg_dist, COUNT(*) count_gw, COUNT(kol) count, COUNT(DISTINCT kol) count_dist, SUM(kol) sum_all, SUM(DISTINCT kol) sum_dist FROM Test_agr; zawierał parami różne liczby. Odp: CREATE TABLE Test_agr ( nazwa VARCHAR(20), kol NUMBER ); INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO Test_agr Test_agr Test_agr Test_agr Test_agr Test_agr VALUES ('nazwa1','10'); VALUES ('nazwa1','20'); VALUES ('nazwa2','20'); VALUES ('nazwa2','30'); VALUES ('nazwa2','40'); (nazwa) VALUES ('nazwa3'); Zadanie 2. W której linii jest błąd? SELECT film_id "ID filmu", tytul AS "Tytuł", tytul AS Tytuł FROM Filmy WHERE budzet > 10 AND "ID filmu" > 2 ORDER BY "ID filmu"; Odp: 4. Alias kolumny nie może być użyty w klauzuli WHERE. W ORDER BY możemy go użyć. SELECT film_id "ID filmu", tytul AS "Tytuł", tytul AS Tytul FROM Filmy WHERE budzet > 10 AND film_id > 2 ORDER BY "ID filmu"; Zadanie 3. Który operator A-D może zastąpić OR w poniższym zapytaniu: SELECT film_id, tytul FROM Filmy WHERE film_id = 2 OR film_id = 6; A. IN B. BETWEEN .. AND .. C. LIKE D. <= E. >= Odp: A. WHERE film_id IN (2,6) Zadanie 4. Które z poniższych SQL zapytań z tabeli Pracownicy(imie, nazwisko, pensja, wydzial, data_zatrudnienia) zwraca imie, nazwisko i pensje pracownikow z wydzialu 4. A. SELECT imie nazwisko pensja FROM Pracownicy ORDER BY nazwisko WHERE wydzial = 4; B. SELECT imie, nazwisko, pensja FROM Pracownicy ORDER BY nazwisko ASC WHERE wydzial = 4; C. SELECT imie nazwisko pensja FROM Pracownicy WHERE wydzial = 4 ORDER BY nazwisko ASC; D. SELECT imie, nazwisko, pensja FROM Pracownicy WHERE wydzial = 4 ORDER BY nazwisko; E. SELECT imie, nazwisko, pensja FROM TABLE Pracownicy WHERE wydzial IS 4 ORDER BY nazwisko ASC; Odp: D CREATE TABLE Pracownicy ( imie VARCHAR(20), nazwisko VARCHAR(20), pensja NUMBER, wydzial NUMBER, data_zatrudnienia DATE ); Zadanie 5. Znajdź błąd w poniższym zapytaniu i popraw. SELECT tytul, AVG(ALL dochod) ,count(*) "liczba filmow" from Filmy where film_id > 0 and count(*) > 4 group by studio_id order by "liczba filmow" DESC; Odp: SELECT studio_id, AVG(ALL dochod) ,count(*) "liczba filmow" FROM Filmy wHERE film_id > 0 GROUP BY studio_id HAVING count(*) > 4 ORDER BY "liczba filmow" DESC; Można też tak: SELECT studio_id, AVG(ALL dochod) ,count(*) "liczba filmow" FROM Filmy wHERE film_id > 0 GROUP BY studio_id HAVING count(*) > 4 ORDER BY 3 DESC; ale tak już nie zadziała (dlaczego ?): SELECT studio_id, AVG(ALL dochod) ,count(*) "liczba filmow" FROM Filmy wHERE film_id > 0 GROUP BY studio_id HAVING "liczba filmow" > 4 ORDER BY 3 DESC; Zadanie 6. Porównaj zapytania, które są błędne i dlaczego? SELECT MIN(wiek), MAX(wiek) FROM Ludzie; SELECT MIN(wiek), MAX(wiek) FROM Ludzie GROUP BY kraj; SELECT kraj, MIN(wiek), MAX(wiek) FROM Ludzie GROUP BY kraj; SELECT kraj, MIN(wiek), MAX(wiek) FROM Ludzie GROUP BY wiek; SELECT MIN(wiek), MAX(wiek) FROM Ludzie GROUP BY wiek; Zadanie 7. Dlaczego poniższe zapytanie nie jest poprawne? SELECT nazwisko Nazwisko2, MAX(wiek) FROM Ludzie WHERE LOWER(nazwisko) LIKE '%ski%' GROUP BY kraj HAVING COUNT(*) > 2; A. GROUP BY nie zawiera kolumny. B. Warunek COUNT(*) > 20 powinien być w klauzuli WHERE. C. GROUP BY musi zawierać funkcje agregującą użytą na liście SELECT. D. HAVING może zawierać tylko funkcje agregujące użyte na liście SELECT. Odp: A. GROUP BY musi zawierać kolumnę względem, której jest grupowanie. Nie można użyć aliasów. SELECT nazwisko Nazwisko, MAX(wiek) FROM Ludzie WHERE LOWER(nazwisko) LIKE '%ski%' GROUP BY kraj, nazwisko; Zadanie 9. Czy poprawne jest poniższe zapytanie? SELECT max(wiek) FROM Ludzie WHERE min(wiek) > 15; Odp: Nie. Nie można używać funkcji agregujących w klauzuli WHERE. Zadanie 10. Czy poprawne jest poniższe zapytanie? SELECT nazwisko, AVG(distinct wiek) ,COUNT(kraj) kraj_count FROM Ludzie WHERE upper(imie) like 'j%' OR ABS(wiek) > 10 having COUNT(kraj) > 5 ORDER BY 2 DESC; Odp: Nie. Istnieje kolumna nazwisko, która nie jest stałą, ani funkcją grupującą, a więc GROUP BY jest obowiązkowe. SELECT nazwisko, AVG(distinct wiek) ,COUNT(kraj) kraj_count FROM Ludzie WHERE upper(imie) like 'j%' OR ABS(wiek) > 10 GROUP BY nazwisko having COUNT(kraj) > 5 ORDER BY 2 DESC; Ponadto należy zwrócić uwagę na wyrażenie "upper(imie) like 'j%'". To nie jest błąd w języku SQL, lecz wynik tego zapytania będzie zawsze pusty. Powinno być upper(imie) like 'J%'. Złączenia i podzapytania Złączenia SELECT tytul, imie, nazwisko FROM Filmy, Ludzie; SELECT tytul, imie, nazwisko FROM Filmy, Ludzie WHERE director_id=person_id; SELECT Filmy.tytul, Ludzie.imie, Ludzie.nazwisko FROM Filmy, Ludzie WHERE Filmy.director_id=Ludzie.person_id; SELECT F.tytul, L.imie, L.nazwisko FROM Filmy F, Ludzie L WHERE F.director_id=L.person_id; Zadanie 1. Wyświetlić filmy, w których dochód był mniejszy niż pensja pojedynczego aktora SELECT tytul, person_id, dochod, pensja FROM Filmy, Obsada WHERE Filmy.film_id=Obsada.film_id AND Obsada.pensja > Film.dochod; Aliasy do tabel: SELECT DISTINCT P1.person_id, P1.imie, P1.nazwisko FROM Ludzie P1, Ludzie P2 WHERE P1.kraj=P2.kraj AND P1.person_id != P2.person_id; Zadanie 2. Wyświetlić obsadę dowolnie wybranego filmu (np. Rambo) SELECT imie, nazwisko, rola FROM Filmy F, Ludzie L, Obsada O WHERE F.film_id=O.film_id AND L.person_id=O.person_id AND F.tytul="Rambo"; Złączenia LEFT JOIN, RIGHT JOIN: SELECT imie, nazwisko, tytul FROM Ludzie, Filmy WHERE person_id=director_id; SELECT imie, nazwisko, tytul FROM Ludzie LEFT JOIN Filmy ON person_id =director_id; SELECT imie, nazwisko, tytul FROM Ludzie RIGHT JOIN Filmy ON person_id =director_id; Suma: UNION SELECT studio_id, kraj FROM Studia UNION SELECT person_id, kraj FROM Ludzie; Podzapytania. Na poziomie WHERE lub HAVING stosujemy operatory: =,<,>, IN, NOT IN, EXISTS, NOT EXISTS, ANY, ALL Zadanie. Wyświetlić tytuł filmu o maksymalnym dochodzie to nie zadziala (dlaczego?): SELECT tytul, MAX(dochod) FROM Filmy; to nie jest rozwiązaniem SELECT MAX(dochod) FROM Filmy; rozwiazanie SELECT tytul FROM Filmy WHERE dochod = (SELECT MAX(dochod) FROM Filmy); Poniższe podzapytanie SELECT tytul FROM Filmy WHERE director_id IN ( SELECT person_id FROM Ludzie WHERE Ludzie.kraj='PL' ); jest równoważne z SELECT tytul FROM Filmy, Ludzie WHERE director_id=person_id AND Ludzie.kraj='PL'; SELECT S.nazwa FROM Studia S WHERE NOT EXISTS (SELECT tytul FROM Filmy WHERE studio_id=S.studio_id); SELECT imie, nazwisko FROM Ludzie L WHERE 10<= ANY (SELECT pensja FROM Obsada O WHERE L.person_id=O.person_id); Zadanie 3. Powyższe zapytanie (z "ANY") przerobić na równoważne zapytanie wykorzystując a. "EXISTS" b. złączenia Zadanie 4. Wyświetlić tytuły filmów, których reżyser jest Polakiem i ma co najmniej 40 lat. Rozwiązać na dwa sposoby, wykorzystując podzapytania i złączenia. Przykłady: 1. Filmy, których budżet był większy niż średni budżet dla wszystkich filmów: SELECT tytul, budzet FROM Filmy WHERE budzet > (SELECT avg(budzet) FROM Filmy); 2. Studia filmowe, które wyprodukowały filmy, gdzie aktorom wypłacono więcej pieniędzy niż cały wypracowany przez film przychód: SELECT nazwa FROM Studia WHERE studio_id IN (SELECT studio_id FROM Filmy WHERE budzet < (SELECT SUM(pensja) FROM Obsada WHERE Filmy.film_id=film_id) ); Zadanie 5. Zapoznać się z poniższymi zapytaniami i zinterpretować ich działanie SELECT film_id, SUM(pensja) FROM Obsada O GROUP BY film_id HAVING SUM(pensja) > (SELECT budzet FROM Filmy WHERE film_id=O.film_id); DELETE FROM Filmy WHERE budzet < (SELECT SUM(pensja) FROM Obsada WHERE Filmy.film_id=film_id); UPDATE Filmy SET budzet=budzet*3 WHERE studio_id IN (SELECT studio_id FROM Studia WHERE kraj='PL'); INSERT INTO Studia (studio_id,nazwa,miasto,kraj) VALUES (25,'Moje Studio','Torun',(SELECT kraj FROM Ludzie WHERE person_id=1)); Widoki (perspektywy): CREATE VIEW Film_rezyser AS SELECT tytul,director_id FROM Filmy; SELECT * FROM Film_rezyser; CREATE VIEW Film_rezyser (tytul,rezyser) AS SELECT tytul,director_id FROM Filmy; Zadania Zadanie 1. Utwórz w SQL perpektywę, która zawiera tylko nazwy studiów filmowych, w których łączny budżet wyprodukowanych filmów jest większy niż 10. Zadanie 2. Dane są trzy tabele Przedmioty(kod_p, nazwa, prowadzacy) Studenci(nr_indeks, nazwisko, wydzial) Egzaminy(nr_indeks, kod_p, ocena) Utwórz powyższe tabele uwzględniając klucze główne. W tabeli egzaminy określ klucze obce. Zadanie 3. Utwórz w SQL zapytanie, które znajduje nazwiska wszystkich studentów, którzy nie otrzymali z żadnego egzaminu oceny > 4. Zadanie 4. Utwórz w SQL zapytanie, które dla każdego przedmiotu podaje jego nazwę i ilość osób, które zdawały egzamin z tego przedmiotu. Zadanie 5. Utwórz w SQL perspektywę, która dla każdego przedmiotu podaje jego nazwę i ilość osób, które zdały egzamin z tego przedmiotu. Zadanie 6. Utwórz w SQL zapytanie, które znajduje nazwiska wszystkich studentów, którzy nie otrzymali z żadnego egzaminu oceny > 4. Zadanie rozwiąż na dwa sposoby (złączenia i podzapytania). Zadanie 7. Utwórz w SQL kod podwyższający o 100 zł. kwotę stypendium studentom z Wydziału Matematyki i Informatyki (np. wydzial=WMiI) z wyjątkiem studentów I roku. Zadanie 8. Utwórz w SQL tabelę (bez klucza głównego): Stypendia(nr_indeks, rok_stud, kwota_styp). Napisz w SQL fragment kodu podwyższający o 20% kwote_styp wszystkim studentom z wyjątkiem studentów I roku. Zadanie 9. Zmodyfikuj definicję powyższej tabeli Stypendia, określając klucz główny nr_indeks. Użyj „ALTER TABLE”. Zadanie 10. Usuń kolumnę rok_stud z tabeli Stypendia. Następnie dodaj kolumnę rok_stud do tabeli Studenci.