Mame tabulky
Odberatel (#ID, jmeno, pocatek_spoluprace)
Zbozi (#ID, nazev, cena, popis)
Odber (#ID_zbozi, #ID_odberatel).
Primarni klice jsou oznaceny symbolem #, atributy ID_zbozi a
ID_odberatel v tabulce Odber jsou cizí klice do tabulky
Zbozi a Odberatel. Tabulka Odber obsahuje jako
radky zaznamy o odberu jednoho kusu daneho zbozi danym
odberatelem.
Skupina A: Vytvorte dotaz pro databazový system Oracle,
ktery vypise jmena odberatelu, kteri odebrali alespon 3 kusy
zbozi, kazdy s cenou vyssi nez 50000.
Reseni:
Reseni muze byt (jako obvykle) nekolik, napriklad bez vyuziti JOIN muze vypadat nasledovne:
SELECT jmeno FROM Odberatel WHERE ID IN (
SELECT ID_odberatel FROM Odber
WHERE id_zbozi IN (
SELECT ID FROM Zbozi WHERE cena > 50000
)
GROUP BY ID_odberatel
HAVING COUNT(id_odberatel) >= 3
);
Nejvnitrnejsi select nejprve vybere ID toho zbozi, ktere stoji nad 50000. Nasledne provedeme
GROUP nad zbylym zbozim v tabulce Odber a vybereme odberatele s vice jak tremi kusy zbozi.
Skupina B: Vytvorte dotaz pro databazovy system Oracle,
ktery vypise jména odberatelu, kteri maji dobu spoluprace drive nez
od roku 2001 a kteri zaroven odebrali mene nez 5 kusu zbozi.
Reseni:
Toto zadani obsahuje (neumyslnou) zaludnost. Pokud vypisete jmena tech odberatelu, kteri maji
v tabulce Odber mene nez 5 zaznamu, tak se vam nezobrazi ti odberatele, kteri neodebrali ani
jeden kus zbozi.
Spravne reseni tedy muze vypadat treba takto:
SELECT jmeno FROM Odberatel
WHERE pocatek_spoluprace < 2001 AND
id NOT IN (
SELECT id_odberatel FROM Odber
GROUP BY id_odberatel HAVING COUNT(*) > 4
);
Vnoreny select vybere ty odberatele, ktery odebrali 5 a vice kusu zbozi a vypiseme jmena tech,
kteri do teto skupiny nepatri. Reseni pomoci OUTER JOIN je take mozne, ale je nutne mit na pameti,
ze nasledne pomoci COUNT nerozlisite, zda dany odberatel ma ve vysledku COUNT(*) z toho duvodu,
ze odebral jedno zbozi a nebo z toho duvodu, ze ma u odebraneho zbozi NULL. V tomto prikladu to
ale nevadi, nebot hranici mame az od 5 kusu zbozi.
Caste chyby:
- Neprovedeno spojeni (JOIN) mezi tabulkami za klausuli FROM. Pokud neprovede spojeni
(... WHERE tab1.id = tab2.id) pro vsechny tabulky uvedene za FROM, vysledkem bude uplny
kartezky soucin, coz nejspis nebude to, co chcete. (viz. cv. 5)
- Pro testovani pritomnosti prvku v mnozine, ktera ma vice prvku je treba pouzit klausuli
'IN' nebo '= ANY', nikoli jednoduche '='. (viz cv. 4)
- Select z vysledku aplikace klausule GROUP BY muze byt proveden pouze na atributy, ktere
jsou uvedeny jako parametry GROUP BY. Napr. SELECT a, b FROM tab GROUP BY a; je spatne.