Comments 18
Эм… А разве сортировка текста идёт не по кодам символов? Цифры так же обладают своим кодом и поэтому так же прекрасно отсортируются. Разве не так?
Ваше решение, судя по всему, основывается на специфике(или же на баге) платформы базы данных, которую вы используете. А платформу вы не указываете.
На моей платформе данный подход неизбежно приводит к ORA-01722: invalid number
На моей платформе данный подход неизбежно приводит к ORA-01722: invalid number
Имелся в виду MySQL, в котором строки в данном случае приводятся к числам
dev.mysql.com/doc/refman/5.0/en/type-conversion.html
dev.mysql.com/doc/refman/5.0/en/type-conversion.html
Не знаю, как в других БД, но в MySQL ваше решение некорректно. Например, таблица из элементов «8», «9», «2.2 Android», «2.3 Android» сортируется как «2.2 Android», «2.3 Android», «8», «9», хотя, насколько я понимаю задание, «8» и «9» должны быть первыми.
Ну. На вскидку, нужен еще один столбец с числовым значением. Его можно сразу генерить во время insert в таблицу, но у меня сейчас нет времени писать правильный create table, так что как-то так:
Боюсь вас расстроить, но в MySQL ваш запрос будет работать не правильно:
результат будет:
1, 1a,…
SELECT *, value=0 FROM
(
SELECT '1' AS VALUE UNION
SELECT '03' AS VALUE UNION
SELECT '10' AS VALUE UNION
SELECT '1.1' AS VALUE UNION
SELECT 'z' AS VALUE UNION
SELECT '1a' AS VALUE UNION
SELECT '2' AS VALUE
) AS t ORDER BY value=0, -value DESC, value
результат будет:
1, 1a,…
мой вариант для MySQL:
SELECT * FROM
(
SELECT '1' AS VALUE UNION
SELECT '03' AS VALUE UNION
SELECT '10' AS VALUE UNION
SELECT '1.1' AS VALUE UNION
SELECT '0..1' AS VALUE UNION
SELECT 'z' AS VALUE UNION
SELECT '1z' AS VALUE UNION
SELECT '2' AS VALUE
) AS t ORDER BY
value REGEXP '^-?[0-9\.]+$' AND LENGTH(value) - LENGTH(REPLACE(value, '.', '')) < 2 DESC,
CAST(value AS UNSIGNED), value;
но за попытку — зачёт
На MS SQL вполне решается «в лоб», думаю на большинстве других СУБД тоже. Непонятно почему гугл откопал только регулярные выражения и триггеры. Так-то можно и триггером, от условий зависит.
declare @t table(name varchar(50));
insert @t values ('12'); insert @t values ('6');
insert @t values ('Android 2.2'); insert @t values ('Android 2.3'); insert @t values ('BlackBerry');
select name from @t
order by case when isnumeric(name) = 0 then name else '' end,
case when isnumeric(name) = 0 then -1 else cast(name as int) end
Если MySQL, то да, там isnumeric нет, то есть сортировка в моём варианте будет выглядеть так (а уж насколько хорошо для MySQL — я не настолько его знаю):
case when name REGEXP '^-?[0-9]+$' then '' else name end,
case when name REGEXP '^-?[0-9]+$' then cast(name as signed) else -1 end
MySQL особым образом выполняет преобразование строки в число, эту особенность весьма ловко использовал автор в своем решении. Ссылку на демонстрацию этой особенности в документации он оставил в коментариях.
Есть мнение, что эта особенность не решает поставленную задачу, что уже отмечено в комментарии выше.
Я бы сэмулировал isnumeric() при помощи, скажем, CONCAT(value+0)=value. Интересно, что проверка value=value+0 всегда истинна, даже если value='String'. Важно перед сравнением явно обратно привести тип к строке при помощи CONCAT().
Oracle:
OREDER BY to_number(regexp_substr(value,'^[0-9]+')),
to_number(regexp_substr(value,'\$[0-9]+')),
value
Sign up to leave a comment.
Сортировка текстового поля как числа и как строки одновременно в MySQL