Естественная сортировка в MySQL с помощью условия ORDER BY

В этой статье мы расскажем о различных методах естественной сортировки MySQL с помощью условия ORDER BY. Давайте начнем урок с простых данных.

Предположим, у нас есть таблица items, которая содержит два столбца: id и item_no. Чтобы создать элементы таблицы мы используем оператор CREATE TABLE:

CREATE TABLE if not exists items(
    id INT AUTO_INCREMENT PRIMARY KEY,
    item_no VARCHAR(255) NOT NULL
);

Мы используем оператор INSERT, чтобы добавить некоторые данные в таблицу items:

INSERT INTO items(item_no)
VALUES ('1'),
       ('1C'),
       ('10Z'),
       ('2A'),
       ('2'),
       ('3C'),
       ('20D');

Когда мы отбираем данные и отсортируем их по признаку item_no, мы получим следующий результат:

SELECT item_no
FROM items
ORDER BY item_no;
item_no

Это не то, что мы ожидали. Мы хотели увидеть результат следующим образом:

результат

Это называется естественной сортировкой. К сожалению, MySQL не предоставляет пользователям встроенный сценарий или функцию естественной сортировки. Оператор ORDER BY сортирует строки в линейном порядке, т.е. один символ за раз, начиная с первого символа.

Чтобы решить эту проблему, в первую очередь мы разобьем столбец item_no на два столбца: prefix и suffix.

Столбец prefix будет содержать цифровую часть item_no, а столбец suffix — буквенную. Это позволит нам отсортировать данные, используя эти два столбца, с помощью следующего запроса:

SELECT CONCAT(prefix,suffix)
FROM items
ORDER BY prefix, suffix

Запросив сортировку данных сначала по числовому признаку, а затем по алфавиту, мы получаем желаемый результат.

Недостатком этого решения является то, что, прежде чем добавлять или обновлять данные, мы должны делить item_no на две части. Кроме того, мы должны объединить два столбца в один, когда мы выбираем данные.

Если в item_no содержатся данные стандартного формата, вы можете использовать следующий запрос, чтобы выполнить естественную сортировку без изменения структуры таблицы.

SELECT item_no
FROM items
ORDER BY CAST(item_no AS  UNSIGNED), item_no;

В этом запросе мы сначала конвертируем данные item_no в целое число без дробей с помощью функции CAST. А также используем условие ORDER BY , чтобы отсортировать строки сначала по числовому признаку, а затем по алфавиту.

Давайте рассмотрим стандартный набор данных, с которыми нам часто приходится иметь дело:

TRUNCATE TABLE items;
 
INSERT INTO items(item_no)
VALUES('A-1'),
      ('A-2'),
      ('A-3'),
      ('A-4'),
      ('A-5'),
      ('A-10'),
      ('A-11'),
      ('A-20'),
      ('A-30');

Мы хотим, чтобы результат сортировки выглядел следующим образом:

результат сортировки

Чтобы этого достичь, мы можем использовать функцию LENGTH. Обратите внимание, что функция LENGTH возвращает длину строки.

Идея состоит в том, чтобы отсортировать данные item_no по длине, а затем по значениям граф при следующем запросе:

SELECT item_no
FROM items
ORDER BY LENGTH(item_no),
         item_no;

Как видите, данные отсортированы естественно.

В случае если в вашей ситуации все выше приведенные решения неприменимы, вам придется выполнить естественную сортировку с помощью отдельных приложений.

Некоторые языки поддерживают функцию естественной сортировки, например, PHP поддерживает функцию natsort() function, которая сортирует массив с использованием алгоритмов естественной сортировки.

Перевод статьи «MySQL Natural Sorting with ORDER BY clasuse» был подготовлен дружной командой проекта Сайтостроение от А до Я.