Mysql сортировка номеров версий
У меня есть значения как:
1.1.2
9.1
2.2
4
1.2.3.4
3.2.14
3.2.1.4.2
.....
Мне нужно отсортировать эти значения с помощью mysql. Тип данных для этого является varbinary (300).
Желаемый результат будет выглядеть так:
1.1.2
1.2.3.4
2.2
3.2.1.4.2
3.2.14
4
9.1
Запрос:
select version_number from table order by version_number asc
он не дает правильного порядка сортировки.
Требуемый результат:
1.1.2
1.2.3.4
2.2
3.2.1.4.2
3.2.14
4
9.1
Номера версий могут содержать до 20 цифр (например, 1.2.3.4.5.6.7.8.9.2.34) и многое другое. Нет особого максимального размера, и стандартная версия так же, как и выше.
Ответы
Ответ 1
Попробуйте использовать функцию INET_ATON
для сортировки следующим образом:
SELECT version_number FROM table ORDER BY INET_ATON(SUBSTRING_INDEX(CONCAT(version_number,'.0.0.0'),'.',4))
Этот трюк был первоначально размещен в списке рассылки mysql, поэтому большое спасибо оригинальному плакату, Майклу Стассену!
Вот что он должен был сказать:
Если каждая часть не превышает 255, вы можете использовать INET_ATON() для выполнения что вы хотите (до 4-й части). Трюк делает каждый из этих сначала взгляните на IP, используя CONCAT, чтобы добавить "0.0.0", чтобы убедиться, что каждый строка имеет не менее 4 частей, затем SUBSTRING_INDEX, чтобы вытащить только первые 4 части.
Теперь я должен указать, что, поскольку мы сортируем по функции столбца, а не на самом столбце, мы не можем использовать индекс на чтобы помочь с сортировкой. Другими словами, сортировка будет относительно медленно.
В последнем случае он рекомендует решение, аналогичное решению, которое отправляется @spanky (отдельные столбцы).
Ответ 2
Я бы сохранил его в трех отдельных столбцах, по одному для каждой части номера версии.
Сделайте каждый столбец TINYINT и даже создайте индекс в трех столбцах. Это должно сделать вещи простыми.
Тогда вы можете сделать:
select CONCAT(v1,'.',v2,'.',v3) AS version_number FROM table ORDER BY v1 asc, v2 asc, v3 asc
Ответ 3
Если вы хотите поддерживать версии типа 1.1-beta
или используя старые версии MySql без INTE_ATON
, вы можете получить один и тот же вид, разделив версию и отсортировав каждую часть как целое число и строку:
SELECT
version,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 1), LENGTH(SUBSTRING_INDEX(version, '.', 1 - 1)) + 1), '.', '') v1,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 2), LENGTH(SUBSTRING_INDEX(version, '.', 2 - 1)) + 1), '.', '') v2,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 3), LENGTH(SUBSTRING_INDEX(version, '.', 3 - 1)) + 1), '.', '') v3,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 4), LENGTH(SUBSTRING_INDEX(version, '.', 4 - 1)) + 1), '.', '') v4
FROM
versions_table
ORDER BY
0+v1, v1 DESC, 0+v2, v2 DESC, 0+v3, v3 DESC, 0+v4, v4 DESC;