» »

[MariaDB] ORDER BY črke, številke in potem znaki

[MariaDB] ORDER BY črke, številke in potem znaki

HotBurek ::

Dobro jutro.

Evo, spet smo tu.

Tokrat me zanima, če MariaDB ponuja kak način, da bi ORDER BY razvrstil po sledečem vrstnem redu:

- najprej črke po abecedi
- potem številke od 0 do 9
- potem pa še znake

Trenutno testiram na stolpcu VARCHAR, ki ima COLLATION utf8mb4_bin, in za ORDER BY dobim sledeč rezultat:

keyword|
-------+
test   |
test'  |
test-  |
test1  |
test2  |
testa  |
testb  |

Glih kontra od tega, kar bi rada.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Liker ::

Lahko narediš custom collation. Google bo pomagal do nekaj začetnih informacij, več bo pa tak hotshot programer, kot si sam, že stuhtal.

mr_chai ::

Super zanimivo vprašanje! Gremo lepo po vrsti.

Trenutno imaš v MariaDB stolpec VARCHAR z utf8mb4_bin collation.
utf8mb4_bin pomeni "binary" primerjava -- torej strežnik gleda surode bajte Unicode znakov, nič posebne logike za črke, številke, simbole.
Zato tudi vidiš, da na primer ' (apostrof) pride pred 1 (številko), ker v Unicode/Binary ima ' nižjo vrednost.

Ti pa želiš naslednje pravilo v ORDER BY:

Najprej črke A-Ž (normalna abeceda),

Nato številke 0-9,

Nato drugi znaki (npr. -, ', ipd.).

Tak vrstni red ni standardni vrstni red nobenega Collation-a v MariaDB -- zato ga moramo sami umetno "zgraditi" v ORDER BY.
Rešitev je: preračunati "prioriteto" za vsak vnos.


Rešitev: uporabimo CASE v ORDER BY
Lahko napišeš nekaj takega:



SELECT keyword
FROM your_table
ORDER BY
  CASE
    WHEN keyword REGEXP '^[a-zA-Z]' THEN 1  -- začne se s črko
    WHEN keyword REGEXP '^[0-9]' THEN 2      -- začne se s številko
    ELSE 3                                  -- vse ostalo (znaki ipd.)
  END,
  keyword COLLATE utf8mb4_unicode_ci;         -- potem normalno po abecedi


Kaj ta poizvedba naredi:

CASE določi "skupino":

1 za črke

2 za številke

3 za vse ostalo

Nato znotraj vsake skupine še normalno sortiraš po abecedi.

Opomba: uporabim utf8mb4_unicode_ci, da črke sortirajo normalno ne glede na binarno vrednost.

? Če želiš še bolj strogo, da NE gleda samo prvega znaka, ampak vse:
Recimo, če želiš, da:

vse kar je čisto črkovno (npr. testa) pride pred test1 -> potem moraš malo bolj zapleteno.

Takrat bi rabil več CASE pogojev ali celo dodatno pomočno kolumno (recimo tip vnosa).


sauce: ChatGPT... use it!

Zgodovina sprememb…

  • spremenilo: mr_chai ()

klemenSLO ::

TOle ne vem če bo ok. Ker je pogoj le na ZAČETEK besede.

morda takole:
ORDER BY
CASE
WHEN keyword REGEXP '^[a-zA-Z]+$' THEN 1 -- samo črke (brez številk in znakov)
WHEN keyword REGEXP '^[a-zA-Z]+[0-9]+$' THEN 2 -- črke + številke
ELSE 3 -- vse ostalo (znaki ipd.)
END,
keyword
Life is not measured in minutes, but in MOMENTS...

Liker ::

Khm.
Pravi način je custom collation, vse drugo bo delovalo mnogo mnogo počasneje, sploh če bo Burek implementiral to na textovnih poljih "poljubne" velikosti z miljoni na miljone vnosov.

Custom collation se naredi tako, da se definira/extenda charset v /usr/share/mysql/charsets/Index.xml (ali kjerkoli že imaš mariadb inštaliran - pazi, vseeno je mapa mysql), tako da se doda custom collation. Nato se ta custom collation naredi v LDML sintaksi (tule je snippet za delček tega).
Ampak tole ni za tiste faint of heart. Je treba znati dejansko brati (in razumeti) dokumentacijo in kompleksna navodila. 95% "programerjev" tega ne sfolga.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[MariaDB] - Brisanje tistih duplikatov, ki imajo višji id

Oddelek: Programiranje
9338 (170) socialec
»

[MariaDB] Zakaj SQL enači "ab " z "ab" v WHERE pogoju?

Oddelek: Programiranje
101141 (726) DamijanD
»

[MariaDB] Kako definirat tabelo, da bo index ločil med "a" in "ä"?

Oddelek: Programiranje
7893 (607) Miha 333
»

[php] encoding niza

Oddelek: Izdelava spletišč
174048 (1963) BivšiUser2
»

Kako dobit šumnik iz baze

Oddelek: Izdelava spletišč
82889 (2747) MRB0rYS

Več podobnih tem