5.1 Vnorený dopyt jednoriadkový
Vnorený dopyt
V niektorých situáciách potrebujeme pred vykonaním hlavného dopytu získať nejaký pomocný údaj. V praxi je to možné riešiť na úrovni aplikácie (napr. PHP), no i SQL jazyk samotný nám dáva možnosť využívať vnorený dopyt (subquery). Hlavný dopyt nazývame vonkajší (outer) a v ňom vnorený dopyt je vnútorný (inner).
Vnútorný dopyt celý uzatvárame do bežných zátvoriek a údaje môže (ale nemusí) čerpať z úplne inej tabuľky ako vonkajší dopyt. Vnútorný dopyt sa vždy vykonáva len raz (teda neznižuje efektivitu), a to pred vonkajším dopytom. Výnimkou je takzvaný „korelujúci vnorený dopyt“, ktorým sa budeme zaoberať v kapitole „5.3 Vnorený dopyt korelujúci“.
Jednoriadkový vs. viacriadkový
Je veľmi dôležité rozlíšiť, či vnútorný dopyt vždy a za každých okolností (pri akýchkoľvek dátach) vráti len jeden riadok výsledkov - vtedy ho nazývame jednoriadkový (single-row) alebo môže potenciálne vrátiť aj viac riadkov - vtedy ho nazývame viacriadkový (multiple-row).
Jednoriadkový vnorený dopyt
Jednoriadkový vnorený dopyt sa typicky používa v klauzule WHERE alebo HAVING. Keďže vracia len jeden riadok výsledkov a obvykle ním získavame len jeden stĺpec, môžeme hodnotu vybraného stĺpca porovnávať využitím bežných operátorov (=, !=, <, >, <=, >=).
Vnorené dopyty je často možné využívať aj ako náhradu spájania tabuliek, napríklad ak chceme počet zamestnancov z oddelenia „IT“, môžeme využiť spojenie tabuliek alebo vnorený dopyt:
-- riešenie cez spojenie tabuliek
SELECT COUNT(*)
FROM employees e
JOIN departments d USING(department_id)
WHERE d.department_name = 'IT';
-- riešenie cez vnorený dopyt:
SELECT COUNT(*)
FROM employees
WHERE department_id = (
SELECT department_id
FROM departments
WHERE department_name = 'IT'
);
V prípade tohto vnoreného dopytu si musíme byť istí, že nemôžu existovať viaceré oddelenia s menom „IT“, inak by dopyt zlyhal! Nešlo by totiž o jednoriadkový dopyt. V ďalšej kapitole sa naučíme, ako sa s tým vysporiadať.
Využitie agregácie
Vo vnorených dopytoch môžeme využívať agregačné funkcie, napríklad pre zistenie priemeru / súčtu / minima / maxima. V takom prípade máme zaručené, že pôjde o jednoriadkový dopyt (pokiaľ nepoužívame zoskupovanie).
Vnorený dopyt ako zdroj údajov
Vnorený dopyt je možné použiť aj v klauzule FROM, čo má význam hlavne pri vnorenej agregácii. Vtedy je však potrebné použiť preň alias (ktorý sa využije ako virtuálna tabuľka):
SELECT názov.stĺpec
FROM (
SELECT stĺpec
FROM …
) AS názov;
Napríklad, ak chceme z prehľadu mien a počtu ich výskytov získať počty a priemery:
SELECT
COUNT(mena.meno) AS "počet mien",
AVG(mena.pocet) AS "priemerný počet výskytov"
FROM (
SELECT
first_name AS meno,
COUNT(*) AS pocet
FROM employees
GROUP BY first_name
) AS mena;
Vnorený dopyt v klauzule FROM je možné realizovať aj prehľadnejšie - výrazom WITH, s ktorým sa zoznámime v kapitole „5.3 Vnorený dopyt korelujúci“. Uvedený príklad by bol:
WITH mena AS (
SELECT
first_name AS meno,
COUNT(*) AS pocet
FROM employees
GROUP BY first_name
)
SELECT
COUNT(meno) AS "počet mien",
AVG(pocet) AS "priemerný počet výskytov"
FROM mena;