Databáze I Přednáška 6
SQL aritmetika v dotazech SQL lze přímo uvádět aritmetické výrazy násobení, dělení, sčítání, odčítání příklad z minulé přednášky: zdvojnásobení platu všem zaměstnancům UPDATE ZAMESTNANEC SET plat = 2* plat;
výpočet platu zaměstnanců v EURech SELECT JMENO, PRIJMENI, PLAT/27.20 FROM ZAMESTNANEC výpočet platu zaměstnanců v EURech, kteří nejsou Češi předpokládám, že nemají rodné číslo, v DB má tedy hodnotu NULL (nesmí být klíčem) SELECT JMENO, PRIJMENI, PLAT/27.20 FROM ZAMESTNANEC WHERE RC IS NULL
SQL agregační funkce COUNT() vrátí počet hodnot SUM() vrátí sumu hodnot AVG() vrátí aritmetický průměr MAX() vrátí maximální hodnotu MIN() vrátí minimální hodnotu
Chování agregačních funkcí obecně agreg_funkce(all DISTINCT sloupec) ALL implicitní volba do výsledku zahrnuje duplicity (duplicitní řádky) DISTINCT do výsledku nezahrnuje duplicity
Chování agregačních funkcí COUNT(sloupec) vrátí počet hodnot ve sloupci sloupec, započítá opakující se hodnoty, hodnoty NULL nezapočítá lze použít DISTINCT aplikována na prázdnou tabulku vrací hodnotu 0 ale: COUNT(*) počítá řádky tabulky, včetně opakujících se a prázdných
Chování agregačních funkcí SUM(sloupec), AVG(sloupec) vrátí součet, resp. aritmetický průměr hodnot sloupce sloupec, započítá opakující se hodnoty, hodnoty NULL nezapočítá lze použít DISTINCT aplikovány na prázdnou tabulku vrací hodnotu NULL SUM(*) ani AVG(*) nelze použít
Chování agregačních funkcí MAX(sloupec), MIN(sloupec) vrátí maximální, resp. minimílní hodnotu ze sloupce sloupec, hodnoty NULL ignoruje použití DISTINCT nemá význam aplikovány na prázdnou tabulku vrací hodnotu NULL MAX(*) ani MIN(*) nelze použít lze je aplikovat i na typy CHAR a DATE
zjištění počtu všech čtenářů v knihovně SELECT COUNT(*) FROM CTENAR; nebo SELECT COUNT(PRIJMENI) FROM CTENAR; zjištění počtu různých příjmení čtenářů v knihovně SELECT COUNT(DISTINCT PRIJMENI) FROM CTENAR;
ČTENÁŘ RČ JMÉNO PŘÍJMENÍ 320612/1234 František Kuldanů 521006/5678 Josef Novák 751002/1256 Jan Novák SELECT COUNT(PRIJMENI) FROM CTENAR; výsledek dotazu: 3 SELECT COUNT(DISTINCT PRIJMENI) FROM CTENAR; výsledek dotazu: 2
zjištění počtu všech exemplářů v knihovně SELECT COUNT(*) FROM EXEMPLAR; zjištění počtu všech exemplářů v knihovně od knihy Babička SELECT COUNT(PRIR_C) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN AND NAZEV="Babička";
zjištění celkové hodnoty exemplářů v knihovně SELECT SUM(CENA)FROM EXEMPLAR; zjištění celkové hodnoty exemplářů v knihovně od knihy Babička SELECT SUM(CENA) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN AND NAZEV="Babička";
zjištění ceny nejdražšího exempláře v knihovně SELECT MAX(CENA)FROM EXEMPLAR; zjištění ceny nejlevnějšího a nejdražšího exemplář od knihy Babička SELECT MIN(CENA),MAX(CENA) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN AND NAZEV="Babička";
Konstrukt GROUP BY umožňuje seskupovat záznamy v tabulce podle hodnoty vybraného sloupce používá se ve spojení s agregačními funkcemi, kdy se neaplikují na celou tabulku, ale na skupinu
zjištění celkové hodnoty exemplářů od jednotlivých titulů v knihovně SELECT KNIHA.NAZEV, SUM(CENA) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN GROUP BY KNIHA.NAZEV;
KNIHA ISBN TITUL AUTOR 80-11111-22-3 U nás A. Jirásek 80-85190-38-9 Babička B. Němcová EXEMPLÁŘ PŘÍR_Č CENA 1 100 2 100 3 150 D_NÁK 25.3.1990 25.3.1990 26.3.1990 ISBN 80-85190-38-9 80-85190-38-9 80-11111-22-3
KNIHA*EXEMPLÁŘ 1 100 12.1.1990 80-85190-38-9 Němcová Babička 2 100 20.3.1990 80-85190-38-9 Němcová Babička 3 150 21.3.1990 80-11111-22-3 Jirásek U nás výsledek dotazu: Babička 200 U nás 150
zjištění počtu exemplářů od jednotlivých ISBN SELECT KNIHA.ISBN, NAZEV, COUNT(PRIR_C) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN GROUP BY KNIHA.ISBN;
KNIHA*EXEMPLÁŘ 1 100 12.1.1990 80-85190-38-9 Němcová Babička 2 100 20.3.1990 80-85190-38-9 Němcová Babička 3 150 21.3.1990 80-11111-22-3 Jirásek U nás výsledek dotazu: 80-85190-38-9 Babička 2 80-11111-22-3 U nás 1
Konstrukt HAVING specifikuje omezení, která data přispívají do výsledku agregačních funkcí za HAVING mohou být pouze seskupovací sloupce nebo agregační funkce HAVING se aplikuje na skupiny specifikované GROUP BY
zjištění počtu exemplářů od jednotlivých ISBN; ve výsledku ponech jen ty knihy, od kterých je počet exemplářů větší nebo roven 10 SELECT KNIHA.ISBN, NAZEV, COUNT(PRIR_C) FROM EXEMPLAR, KNIHA WHERE KNIHA.ISBN = EXEMPLAR.ISBN GROUP BY KNIHA.ISBN HAVING COUNT(PRIR_C)>=10;
agregační funkce mohou být součástí i tzv. poddotazu (hnízděného dotazu): Najdi jména a příjmení všech čtenářů, kteří mají vypůjčeny více než dva exempláře SELECT JMENO,PRIJMENI FROM CTENAR c, WHERE (SELECT COUNT(PRIR_C) FROM SI_VYPUJCIL WHERE RC=c.RC) > 2;
Poznámky: poddotaz vrací jednu hodnotu: tzv. skalární poddotaz poddotaz je závislý na vnějším dotazu tzv. vztažený poddotaz c představuje zafixovaný řádek tabulky CTENAR
Predikáty pro práci s množinami predikát v matematické logice výraz, o kterém lze tvrdit, zda je pravdivý/nepravdivý IN již známe z přechozích příkladů dotazů ANY (ekvivalent SOME) ALL ANY(SOME), ALL lze použít s porovnávacími operátory: <, <=, >, >=, <>, = =SOME je ekvivalentní s IN <>SOME je ekvivaletní s NOT IN
Příklady (z knihy Pokorný: DB systémy): najdi zaměstnance, kteří mají vyšší plat než nějaký Drábek SELECT id_zam, prijmeni FROM ZAMESTNANEC WHERE plat > ANY (SELECT z.plat FROM ZAMESTNANEC z WHERE z.prijmeni = "Drábek");
ZAMĚSTNANEC ID_ZAM JMÉNO PŘÍJMENÍ PLAT 1 Josef Novák 15 000 2 Jan Drábek 10 000 3 Jiří Drábek 20 000 4 Alena Novotná 30 000 5 František Ponocný 8 000 výsledkem poddotazu (platy Drábků) je množina { 10000, 20000 }
podmínku ve vnějším dotazu plat > ANY (SELECT ) splňují platy 15000, 20000, 30000 výsledek dotazu: 1 Novák 3 Drábek 4 Novotná Poznámka: ve výsledku mezi zaměstnanci budou přirozeně všichni Drábkové kromě toho, který má z Drábků nejnižší plat
najdi zaměstnance, kteří mají vyšší plat než všichni Drábkové SELECT id_zam, prijmeni FROM ZAMESTNANEC WHERE plat > ALL (SELECT z.plat FROM ZAMESTNANEC z WHERE z.prijmeni = "Drábek");
podmínku ve vnějším dotazu plat > ALL (SELECT ) splňuje plat 30000 výsledek dotazu: 4 Novotná
Kteří Drábkové mají mezi Drábky nejvyšší plat? SELECT id_zam, prijmeni FROM ZAMESTNANEC x WHERE x.prijmeni="drábek" AND x. plat >= ALL (SELECT z.plat FROM ZAMESTNANEC z WHERE z.prijmeni = "Drábek");
Predikát EXIST EXIST představuje dotaz na neprázdnost (resp. prázdnost ve tvaru NOT EXIST) nějaké množiny nabývá hodnoty true, je-li množina (např. výsledek dotazu) neprázdná
Predikát EXIST najdi čtenáře, kteří mají nějakou výpůjčku SELECT RC, PRIJMENI FROM CTENAR c WHERE EXIST (SELECT * FROM SI_VYPUJCIL v WHERE v.rc = c.rc);
dotaz lze formulovat také pomocí predikátu IN SELECT RC, PRIJMENI FROM CTENAR WHERE RC IN(SELECT RC FROM SI_VYPUJCIL);
Predikát LIKE LIKE používá se pro částečné porovnání řetězců lze použít zástupné znaky: % - 0 nebo více libovolných znaků _ - jeden libovolný znak
Predikát LIKE najdi čtenáře, jejichž příjmení začínají na "No" SELECT RC, PRIJMENI FROM CTENAR WHERE PRIJMENI LIKE "No%";
Predikát UNIQUE otestuje, zda v množině existují duplicity použití s poddotazem: UNIQUE(poddotaz)
Příklady (z knihy Pokorný: DB systémy): vypiš zaměstnance, přičemž ať vždy alespoň 3 pracují na stejné pozici SELECT id_zam, prijmeni, pozice FROM ZAMESTNANEC z1 WHERE NOT UNIQUE (SELECT z2.pozice FROM ZAMESTNANEC z2 WHERE z1.pozice = z2.pozice AND z1.id_zam <> z2.id_zam);
Množinové operace UNION sjednocení INTERSECTION průnik EXCEPT rozdíl aplikují se na poddotazy
Příklady (z knihy Pokorný: DB systémy): najdi filmy, kde hraje W. Allen nebo je režíroval SELECT jm_filmu FROM FILMY WHERE herec="allen" UNION SELECT jm_filmu FROM FILMY WHERE reziserá="allen";
Pohledy - VIEWS pohled = virtuální tabulka obsah pohledu není uložen v databázi jako tabulka představuje definici externího (uživatelského) schématu CREATE VIEW jmeno_pohledu [virt_jmeno_atr_1, virt_jmeno_atr_2, ] AS dotaz [WITH [CASCADE LOCAL] CHECK OPTION];
Pohledy - VIEWS jména virtuálních atributů nemusí být specifikována, pak přebírají se z dotazu WITH CHECK OPTION definuje pohled jako aktualizovatelný jde ho "měnit" definovat pohledy je vhodné, pokud se často dotazujeme na určitá data některé SŘBD umožňují definovat tzv. materializované pohledy, které se ukládají do DB jako tabulka
definujeme pohled: seznam čtenářů s příjmením Novák CREATE VIEW novaci AS SELECT * FROM CTENAR WHERE PRIJMENI = "Novák"; nad pohledem můžeme tvořit další dotazy: vybereme Nováky narozené před 1.1.1970:
pro jednoduchost předpokládáme atribut dat_nar SELECT * FROM novaci WHERE DAT_NAR < 1.1.1970;
definujeme pohled: seznam čtenářů s počtem výpujček CREATE VIEW ctenari_vyp rc jm,pr,poc AS SELECT RC,JMENO,PRIJMENI,COUNT(PRIR_C) FROM CTENAR,SI_VYPUJCIL WHERE CTENAR.RC = SI_VYPUJCIL.RC GROUP BY CTENAR.RC;
Aktualizace pohledů aktualizace pohledu pomocí aktualizačních dotazů INSERT, UPDATE, DELETE aktualizace dat původních tabulek, je-li při definici pohledu dovoleno pomocí WITH CHECK OPTION pokud je pohled postaven nad jednou tabulkou, nevznikají závažné problémy je-li součástí pohledu klíč, lze provádět libovolnou aktualizační operaci, problém může způsobit např.: součástí pohledu není atribut s omezením NOT NULL, vkládáme nový řádek do pohledu není definována hodnota inkriminovaného sloupce
Aktualizace pohledů pokud je pohled postaven jako spojení dvou (více) tabulek, aktualizace znamená aktualizaci dat v těchto tabulkách může vést k problémům s klíčem, opatrně s těmito operacemi
Zrušení pohledu DROP VIEW jmeno_pohledu