Сменить стандартную сортировку по имени mysql

В стандартной сортировке идет сначала 0-9, A-Z, А-я, а нужно наооборот. Делаю так:

ORDER BY `name` REGEXP '[^А-Яа-я]',
         `name` REGEXP '[^A-Za-z]',
         `name` REGEXP '[^0-9]', 
         `name` collate utf8_unicode_ci

И ничего не происходит Почему?


Ответы (2 шт):

Автор решения: Akina

сортировка по первой букве. Сначала кирилица, потом латиница, потом цифрьі

ORDER BY name REGEXP '^[А-я]' DESC,
         name REGEXP '^[A-z]' DESC,
         name REGEXP '^[0-9]' DESC,
         name

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=39e441389cb8f2ec9ac381f62d9feb55

→ Ссылка
Автор решения: Егор Банин

В MySQL за сравнение двух строк отвечает collation. Это правила, которые позволяют базе решить больше ли 'a' чем 'b', равны ли 'a', 'A' и 'ä'. При сортировке по строке, база сравнивает строки с помощью этих правил.

Вы хотите задать свои правила. Это подразумевает, что вам надо создать собственный collation. Но это не такая простая задача как кажется на первый взгляд. Что вы будете делать со знаками препинания, иероглифами и символами эмодзи? Посмотрите сколько тонкостей в алгоритме для юникода. Кроме того, MySQL не предоставляет инструментов создания collation на уровне пользователя базы данных. Я никогда не пробовал провернуть подобное, но вероятно придётся писать на си и компилировать свою версию MySQL.

Однако вашу задачу можно решить проще. Вы можете изменить значения name так, чтобы они сортировались так как надо. Решение в лоб -- рассчитать вес (позицию) каждого имени заранее и сортировать по нему:

name nameWeight
abc 1
123 2
абв 0

Это правильное решение, которое позволяет вам применить любые правила при расчёте. Но у него есть недостаток: вам надо пересчитывать все веса при любом изменении в столбце name. Такие пересчёты могут занимать очень много времени и памяти на большом объёме данных.

Можно схитрить. Напишем перед каждым символом коэффициент в зависимости от того, к какой группе этот символ относится. Для кириллицы -- 0, для букв английского алфавита -- 1, для остальных символов -- 2. Получится такая ерунда:

name rankedName
abc 1a1b1c
123 212223
абв 0а0б0в

Теперь при изменении или добавлении имени в таблицу, достаточно рассчитать только один rankedName.

→ Ссылка