Сменить стандартную сортировку по имени mysql
В стандартной сортировке идет сначала 0-9, A-Z, А-я, а нужно наооборот. Делаю так:
ORDER BY `name` REGEXP '[^А-Яа-я]',
`name` REGEXP '[^A-Za-z]',
`name` REGEXP '[^0-9]',
`name` collate utf8_unicode_ci
И ничего не происходит Почему?
Ответы (2 шт):
сортировка по первой букве. Сначала кирилица, потом латиница, потом цифрьі
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.