Takovým příkazem bude typicky nějaká statistická hodnota, například průměrný plat. Pokud Vás například budou zajímat všichni zaměstnanci s průměrným a nadprůměrným platem, docílíte toho následujícím poddotazem (tabulku zamestnanci jsme vytvořili v kapitole 6 Vytváření relací). Pro zajímavost jsem výsledek setřídil sestupně dle výše platu.
Poddotaz musí být v závorkách a musí vrátit jen jednu hodnotu (jeden sloupec s jedním řádkem).rimmer1=> SELECT * FROM zamestnanci rimmer1-> WHERE plat >= (SELECT AVG(plat) FROM zamestnanci) rimmer1-> ORDER BY plat DESC; jmeno | prijmeni | plat | oddeleni_id | rodne_cislo -------+----------+-------+-------------+------------- Tomas | Mann | 22000 | 3 | 8001010608 Vasek | Trn | 16000 | 3 | 8001010609 Lenka | Pavova | 15000 | 2 | 8001010604 Tom | Jerry | 15000 | 2 | 8001010605 (4 rows)
Například budeme chtít zjistit všechny zaměstnance, kteří pracují v právním oddělení.
Opakem IN je NOT IN.rimmer1=> SELECT * FROM zamestnanci WHERE oddeleni_id IN rimmer1-> (SELECT prim_klic FROM oddeleni WHERE nazev = 'Pravni oddeleni'); jmeno | prijmeni | plat | oddeleni_id | rodne_cislo ---------+----------+-------+-------------+------------- Lenka | Pavova | 15000 | 2 | 8001010604 Tom | Jerry | 15000 | 2 | 8001010605 Martin | Luter | 12000 | 2 | 8001010606 Leopold | King | 13000 | 2 | 8001010607 Tomas | Mann | 22000 | 3 | 8001010608 Vasek | Trn | 16000 | 3 | 8001010609 Stary | Osel | 9000 | 3 | 8001010610 (7 rows)
Například můžete chtít vypsat všechny zaměstnance, kteří mají maximální plat.
ALL Je to to samé jako poddotaz, rozdíl je jen v tom, že hodnotu sloupce (plat) porovnáváme s množinou hodnot, nikoliv s jednou hodnotou.rimmer1=> SELECT * FROM zamestnanci WHERE plat >= ALL (SELECT plat FROM zamestnanci); jmeno | prijmeni | plat | oddeleni_id | rodne_cislo ---------+----------+-------+-------------+------------- Tomas | Mann | 22000 | 3 | 8001010608 (1 rows)
V příkladu vybereme všechny platy, které jsou větší nebo rovny dvojnásobku nejmenšího platu. (Nejmenší plat je 9000. Takže podmínku splní každý plat který je větší nebo roven 18000). Podmínka ANY požaduje splnění podmínky (>=) alespoň u jednoho záznamu. V našem případě tedy stačí, aby byl plat větší než dvojnásobek toho nejmenšího.
rimmer1=> SELECT * FROM zamestnanci WHERE plat >= rimmer1=> ANY (SELECT plat*2 FROM zamestnanci); jmeno | prijmeni | plat | oddeleni_id | rodne_cislo -------+----------+-------+-------------+------------- Tomas | Mann | 22000 | 3 | 8001010608 (1 row)
Pomocí korelovaného dotazu můžeme například vypsat všechny zaměstnance, kteří mají maximální plat v oddělení, ve kterém pracují (Opět vycházíme z příkladu z kapitoly 6 Vytváření relací).
Podívejme se, kde je zakopaný pes. První řádka příkazu je obyčený SELECT až na alias z1. V tuto chvíly bychom vybrali všechny řádky z tabulky zamestnanci (alias z1). Nás však zajímají jen ty řádky z tabulky z1, kde je maximální plat pro řádky se stejnou hodnotu v sloupci oddeleni_id. Tato podmínka je podstatou korelovaného dotazu. Moc dobře se to pochopit nedá, že?rimmer1=> SELECT prijmeni,plat,oddeleni_id FROM zamestnanci z1 rimmer1-> WHERE z1.plat = (SELECT MAX(z2.plat) FROM zamestnanci z2 rimmer1(> WHERE z1.oddeleni_id = z2.oddeleni_id); prijmeni | plat | oddeleni_id ----------+-------+------------- Mala | 12000 | 1 Pavova | 15000 | 2 Jerry | 15000 | 2 Mann | 22000 | 3 (4 rows)
Není důvod, proč si to ještě trochu nezkomplikovat. Místo oddeleni_id bude jistě lepší mít ve výsledku název oddělení. Název oddělení je uložen v tabulce oddeleni, takže musíme předcházející korelovaný dotaz propojit s touto tabulkou.
rimmer1=> SELECT prijmeni,plat,nazev FROM zamestnanci z1, oddeleni rimmer1-> WHERE z1.oddeleni_id = oddeleni.prim_klic AND rimmer1-> z1.plat = (SELECT max (z2.plat) FROM zamestnanci z2 rimmer1(> WHERE z1.oddeleni_id = z2.oddeleni_id); prijmeni | plat | nazev ----------+-------+----------------- Mala | 12000 | Sekretariat Pavova | 15000 | Pravni oddeleni Jerry | 15000 | Pravni oddeleni Mann | 22000 | Pravni oddeleni (4 rows)
