2.7 Výberový dopyt – zoradenie výsledkov
Zoradenie výsledkov
Doteraz sme neriešili poradie riadkov vo výsledku dopytu a nemohli sme mať ani žiadne očakávania. Výsledky boli v nejakom poradí – hoci nešlo o náhodné poradie, dá sa označiť ako nepredvídateľné. V praxi však často chceme mať údaje nejako zoradené – číselné údaje podľa veľkosti, textové abecedne a časové chronologicky.
Vo výberovom dopyte to dosiahneme pridaním klauzuly ORDER BY. Umiestňuje sa za klauzulu WHERE (resp. priamo za FROM, ak podmienku nepoužijeme), teda správne poradie klauzúl je:
- SELECT [DISTINCT] {stĺpce alebo výrazy}
- FROM {tabuľka}
- [WHERE {podmienka}]
- [ORDER BY {kritérium} [DESC]]
- [LIMIT {počet}] [OFFSET {začiatok}];
V klauzule ORDER BY môžeme ako kritérium triedenia špecifikovať stĺpec alebo výraz, podľa ktorého sa výsledky zoradia. Je možné využiť aj alias.
-- abecedný zoznam zamestnancov oddelenia 50
SELECT last_name || ' ' || first_name AS zamestnanec
FROM employees
WHERE department_id = 50
ORDER BY zamestnanec;
Smer zoradenia
Implicitné poradie je od najmenšieho po najväčšie (resp. od A po Z), nie je potrebné explicitne ho uvádzať kľúčovým slovom ASC (ascending). Ak však chceme opačné poradie, musíme uviesť dodatok DESC (descending), napríklad ORDER BY plat DESC.
-- zoznam zamestnancov v poradí od najvyššieho platu
SELECT
last_name || ' ' || first_name AS zamestnanec,
salary AS plat
FROM employees
ORDER BY plat DESC;
Pozornému oku neunikne, že viacerí zamestnanci majú rovnaký plat a sú v nepredvídateľnom poradí.
Zoradenie podľa viacerých stĺpcov
Kritérií triedenia môžeme uviesť aj viac, oddeľujú sa čiarkami a uplatňujú sa v uvedenom poradí. Ďalšie kritérium sa uplatní len v prípade, že nastala zhoda v predošlom.
-- zoznam zamestnancov v poradí podľa čísla oddelenia (od najmenšieho), platu (od najvyššieho) a mena (abecedne)
SELECT
department_id AS oddelenie,
last_name || ' ' || first_name AS zamestnanec,
salary AS plat
FROM employees
ORDER BY oddelenie, plat DESC, zamestnanec;
Zaradenie NULL hodnoty
NULL hodnoty sú pokladané v Oracle SQL a PostgreSQL za najväčšie, v MySQL/MariaDB za najmenšie. V predošlom dopyte sa vo výsledkoch objavil jeden zamestnanec, ktorý nemá uvedené oddelenie. MariaDB ho zaraďuje na začiatok a zatiaľ s tým nevieme nič spraviť. Oracle a PostgreSQL ho zaraďujú na koniec, no môžeme to zmeniť dodatkom NULLS FIRST za kritérium.
-- zoznam zamestnancov v poradí podľa čísla oddelenia (od najmenšieho), platu (od najvyššieho) a mena (abecedne)
SELECT
department_id AS oddelenie,
last_name || ' ' || first_name AS zamestnanec,
salary AS plat
FROM employees
ORDER BY oddelenie NULLS FIRST, plat DESC, zamestnanec;
Časom sa naučíme zmenu poradia NULL hodnôt ovplyvniť aj v MariaDB, využijeme funkciu COALESCE().
Abeceda podľa jazyka
Pozrime sa ešte raz na abecedné poradie, vypíšme abecedný zoznam krstných mien:
SELECT DISTINCT first_name
FROM employees
ORDER BY first_name;
Na prvý pohľad všetko vyzerá v poriadku a jednoznačné. No všimnime si, kde sa nachádzajú mená ako Charles a Christopher – sú zaradené medzi menami začínajúcimi písmenom C. Lenže v slovenskom jazyku patrí písmeno CH až za H. Keď prepíšeme niektoré mená (alebo priezviská) na slovenské, začínajúce písmenami s mäkčeňmi, niektoré budú dokonca úplne mimo poradia, kdesi na konci!
Pri textových dátových typoch je potrebné zohľadňovať aj konkrétny jazyk a jeho poradie zoradenia (collation) – nie je totiž rovnaké v rôznych jazykoch, napríklad „ch“ je v slovenčine za písmenom „h“, ale v angličtine je chápané ako písmeno „c“, nasledované písmenom „h“.
Aké je správne abecedné poradie slov s mäkčeňmi? Je striktne podľa abecedy, teda napríklad v tomto poradí?
„Cesnak, Cibuľková, Čaba, Čučeľ, Delo, Drevo, Ďatlová, Ďuro“Čiastočne áno, ale je tu výnimka – písmená D, T, N a L sa čítajú mäkko, ak za nimi nasledujú samohlásky E, I, preto písmená Ď, Ť, Ň a Ľ zaraďujeme na úrovni D, T, N a L, nie až za nimi. Správne poradie je:
„Cesnak, Cibuľková, Čaba, Čučeľ, Ďatlová, Delo, Drevo, Ďuro“Viac detailov nájdete v jazykovej poradni.
Poradie zoradenia je možné jednorazovo definovať dodatkom COLLATE {poradie triedenia} za kritérium, pričom poradie triedenia je pre slovenčinu:
- v PostgreSQL
"sk-x-icu"(v dvojitých úvodzovkách), zoznam získame príkazomSELECT * FROM pg_collation; - v MySQL/MariaDB
utf8_slovak_ci(bez úvodzoviek).
-- MySQL/MariaDB
SELECT DISTINCT first_name
FROM employees
ORDER BY first_name COLLATE utf8_slovak_ci;
PostgreSQL však vyžaduje tento dodatok aj pre klauzulu SELECT DISTINCT, výhodné je využiť alias, aby sme nemuseli jazyk špecifikovať na dvoch miestach:
-- PostgreSQL
SELECT DISTINCT first_name COLLATE "sk-x-icu" AS meno
FROM employees
ORDER BY meno;
Jazyk môžeme prednastaviť každému stĺpcu už pri vytváraní tabuľky, no i tak ho niekedy potrebujeme spresňovať v dopyte podľa jazykových nastavení pripojeného klienta.