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.