Skip to main content

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íkazom SELECT * 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.