12. Al-lekérdezések (subselect)

Amikor egy lekérdezésben egy másik lekérdezés eredményét szeretnénk felhasználni, jól jön az SQL nyelvek egyik tulajdonsága, a lekérdezések egymásba ágyazásának lehetősége.

Ez bizonyos értelemben hasonló ahhoz, mint programozáskor egymásba ágyazott ciklusokat használunk, de mint minden hasonlat ez is sántít. A lényeg az, hogy az al-lekérdezést mindig előbb hajtja végre a szerver, mint a fő lekérdezést!

Az elméleti megfontolás helyett nézzünk példákat

1. Az iskolai átlagnál jobb átlagú diákok

Ha meg szeretnénk tudni, hogy melyek azok a diákok, akik az iskolai átlagnál jobbak, akkor először az iskolai átlagot kell kiszámolni, majd szűrni azokat, akiknek az átlaga jobb!

​Az al-lekérdezés egy értéket ad vissza, az iskola összes osztályzatának átlagát. A fő lekérdezés ehhez az átlaghoz képest jeleníti meg csak azokat, akik ennél az átlagnál jobbak.

SELECT DID, AVG(*) AS Atlag FROM Diakok 
GROUP BY DID
HAVING Atlag > (SELECT AVG(osztalyzat) AS atlageredmeny FROM Osztalyzatok)

2. Hogyan tudjuk az átlagos létszámnál kisebb létszámú osztályzatokat megkeresni?

Nézzük meg a kiértékelés sorrendje szerinti lekérdezéseket, majd a végén az egész lekérdezést!

A legbelső lekérdezésekkel kezdődik a kiértékelés, azaz kiszámoljuk a tanulók összes létszámát

1.) SELECT DISTINCT Osztaly AS a FROM Diakok

Listát készítünk a különböző osztályokról!

SELECT COUNT( Diakok.DID ) AS sum FROM Diakok

Kiszámoljuk az osztályok számát?

2.) SELECT COUNT(D.a) As db FROM (SELECT DISTINCT Osztaly AS a FROM Diakok) D

Ebben a lekérdezésben a "D" a lekérdezés ALIASA. MYSQL-ben egy lekérdezéshez létrehozhatunk alias nevet, amelyet aztán a lekérdezés többi pontján használhatunk.

Az 1.) és 2.) lekérdezés egy-egy értéket ad eredményül és ezeket elosztjuk egymással. Ezt az SQL-ben úgy tudjuk megoldani, hogy a SELECT után végrehajtjuk a kifejezést és ALIAS nevet adunk neki

SELECT 
 ( SELECT COUNT( diakok.DID ) AS sum FROM diakok ) / 
 ( SELECT COUNT(D.a) AS db FROM (SELECT DISTINCT Osztaly AS a FROM Diakok) D )
 AS Atlag

Végül az így megkapott átlag értéknél a kisebb létszámú osztályok neveit listázzuk ki:

SELECt `Osztaly`, Count(*) AS Fo FROM `diakok`
GROUP BY osztaly
HAVING 
Fo < (
     SELECT 
       ( SELECT COUNT( diakok.DID )  AS sum FROM diakok ) / 
       ( SELECT COUNT(D.a) FROM (SELECT DISTINCT Osztaly AS a FROM Diakok) D )
     AS Atlag
)

Ha bárki azt gondolja, hogy ez könnyű, hát nem az, de működik!

További egyszerűbb példák

váncsiak vagyunk Kiss János osztalytársainak a nevére:

SELECT Nev FROM Diakok WHERE Osztaly =  
(SELECT Osztaly FROM Diakok WHERE Nev = 'Kiss János'); 

Megjegyzés

Ha egy al-lekérdezés eredményét egy összehasonlításban (WHERE, HAVING) szeretnénk használni, akkor az allekérdezés csak egy értéket adhat vissza eredményül.

Allekérdezések esetén gyakran használjuk ugyanazt a táblanevet, mint a fő lekérdezésekben. Ilyenkor a lekérdezésben kötelező ALIAS nevet használni, mert az SQL ennek alapján tudja eldönteni, hogy melyik lekérdezés mezőjét használjuk!