You are on page 1of 47

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 D_NÁK ISBN
1 100 25.3.1990 80-85190-38-9
2 100 25.3.1990 80-85190-38-9
3 150 26.3.1990 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

You might also like