SQL. Alampäringud

Ühe päringu vastus on teise päringu argumendiks.

SELECT field_name FROM table_name WHERE condition ... GROUP BY condition HAVING condition

Selline struktuur ei pea olema kahetasandiline, sügavus võib olla suurem:

SELECT * FROM something WHERE (SUBQUERY(SUBQUERY(SUBQUERY)))

Alampäring võib asetseda päringu lauses ka FROM järel ning HAVING avaldises. Kõige tavalisem asukoht on siiski WHERE tingimuses ja HAVING tingimuses.

WHERE avaldis võrdlusoperaator alampäring
WHERE alampäring võrdlusoperaator avaldis
WHERE alampäring võrdlusoperaator alampäring

Access lubab kõiki neid variante. MySQL lubab alampäringuid alates versioonist 4.1.

Alampäring ei tohi sisaldada käsklust ORDER BY. Alampäringu vastus võib olla:


Kõige lihtsam näide:

SELECT nimi FROM tootajad WHERE osakond = (SELECT osak_nr FROM osakonnad WHERE osak_nimi=’Tallinn’)
kuid ka
SELECT nimi FROM tootajad WHERE osakond = (SELECT osak_nr FROM osakonnad WHERE osak_nimi=’Tallinn’) AND grupp = (SELECT grupi_nr FROM grupid WHERE grupi_nimi='Juhtkond')

Võrdlusoperaatoriks võib olla:
=
<
>
<>
IN
= ANY
< ANY
> ANY
> ALL
<> ALL

SELECT nimi FROM tootajad WHERE palk > (SELECT avg(palk) FROM tootajad)
 

Correlated subquery – alampäringut korratakse iga peapäringu tabeli rea jaoks.

SELECT osakond FROM osakonnad WHERE inimesi_eelm_aastal > (SELECT count(nimi) FROM tootajad WHERE osakonnad.nr=tootajad.osak)

Samasugune korreleeruv alampäring koos rekursiivse seosega. Leida kõik töötajad, kelle palk on suurem kui grupi keskmine palk:

SELECT nimi,grupp,palk FROM tootajad AS n1 WHERE palk > (SELECT avg(palk) FROM tootajad n2 WHERE n1.grupp=n2.grupp);
 

SELECT nimi FROM tootajad WHERE osakond IN (SELECT osak_nr FROM osakonnad WHERE linn=’Tallinn’)
või
SELECT nimi FROM tootajad WHERE osakond, juhataja IN (SELECT osak_nr, juhataja FROM osakonnad WHERE linn=’Tallinn’)

SELECT nimi FROM tootajad WHERE osakond = ANY (SELECT osak_nr FROM osakonnad WHERE linn=’Tallinn’)

ANY  kasutusala on laiem kui IN. Leida 1. osakonna kõik töötajad, kelle palk on suurem vähemalt ühest 2. osakonna töötaja palgast:

SELECT nimi,palk FROM tootaja WHERE osakond=1 and palk > ANY (SELECT palk FROM tootaja WHERE osakond=2)

Leida 1. osakonna kõik töötajad, kelle palk on suurem kõikidest 2. osakonna töötaja palkadest:

SELECT nimi,palk FROM tootaja WHERE osakond=1 and palk > ALL (SELECT palk FROM tootaja WHERE osakond=2)

Operaator <> ALL tähendab “ei ole võrdne mitte ühegagi alampäringu vastustest”. Samuti käitub ka “NOT IN” ja “WHERE NOT avaldis ANY...”

Leida kõik osakonnad, kus keskmine palk on suurem firma keskmisest:

SELECT osakond,avg(palk) FROM tootajad GROUP BY osakond HAVING avg(palk) > (SELECT avg(palk) FROM tootajad)
 

Avaldise ja võrdlusoperaatori asemel võib olla operaator (NOT) EXISTS

SELECT * FROM tootajad WHERE exists (SELECT * FROM tootajad WHERE palk>0)

EXISTS tagastab väärtuse TRUE, kui alampäringu vastuseid on olemas ja väärtuse FALSE, kui alampäringu vastus on tühi.



Alampäring FROM järel

Leida maksimaalne kesmine gruppide keskmistest palkadest:

SELECT max(sum1) AS tulemus FROM (SELECT avg(palk) AS sum1 FROM tootajad GROUP BY grupp) AS t1



Alampäringud lausetes UPDATE, INSERT ja DELETE

UPDATE tootajad SET palk=palk*1.1 WHERE palk < (SELECT avg(palk) FROM tootajad)

INSERT INTO tootajad SELECT * FROM endised_tootajad
INSERT INTO tootajad (list) SELECT (list) FROM endised_tootajad

MySQL-4 lubab kasutada lisatunnust INGORE, et lause struktuuriga vastuolus olevad uued read ei seiskaks lause täitmist.

DELETE FROM tootajad WHERE (palk+1000) < (SELECT avg(palk) FROM tootajad)



Kodutöö

Esitada SQL lause järgmise tabeli loomiseks:
Saateleht = (stlnr, klient, kuupaev, tootaja, summa)

Esitada päring, mis teataks iga töötaja suurima summaga saatelehed. Kasutada grupifunktsiooni.

Esitada päring, mis esitaks kõik töötajad ja nende tehtud sellised saatelehed, mille summa on suurem käesoleva aasta saatelehtede keskmisest. Kasutada grupifunktsiooni ja alampäringut.

Tähtaeg 22.04.2004