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). Keď sú údaje zoradené, začne mať zmysel aj ich „stránkovanie“ – obmedzenie počtu vypísaných riadkov cez LIMIT a definovanie začiatku cez OFFSET. 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.