Строка заказа SQL как число

137

У меня есть номера, сохраненные в VARCHARбазе данных MySQL. Я не могу сделать их INTиз-за некоторых других обстоятельств.

При сортировке они воспринимаются как символы, а не как числа.

В базе данных у меня есть

1 2 3 4 5 6 7 8 9 10...

На моей странице он показывает упорядоченный список следующим образом:

1 10 2 3 4 5 6 7 8 9

Как я могу сделать так, чтобы это выглядело упорядоченным по возрастанию номеров?

Jamol
источник
5
Конечно, вы должны были хранить данные в виде числа, а не строки.
Одд
@Oded У вас могут быть произвольные данные (например, настройки), которые вы хотите упорядочить по числовому значению только в особых случаях.
Glutexo
очень интересная статья - для MSSQL, но должна быть относительно похожа для MySQL: essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Ответы:

256

Если возможно, вам следует изменить тип данных столбца на число, если вы все равно сохраняете числа.

Если вы не можете сделать это затем бросьте ваше значение столбца в integer явном виде с

select col from yourtable
order by cast(col as unsigned)

или неявно, например, с помощью математической операции, которая вызывает преобразование в число

select col from yourtable
order by col + 0

Кстати, MySQL преобразует строки слева направо. Примеры:

string value  |  integer value after conversion
--------------+--------------------------------
'1'           |  1
'ABC'         |  0   /* the string does not contain a number, so the result is 0 */
'123miles'    |  123 
'$123'        |  0   /* the left side of the string does not start with a number */
Юрген д
источник
3
заказ по цв * 1 работает отлично. Какая магия стоит за этим? Извините, я не профессионал, так что это может быть глупый вопрос, но как * 1 меняет его на число?
Джамол
12
MySQL автоматически преобразует строку в число для умножения на1
juergen d
1
Первый вариант является наиболее подходящим, второй имеет дополнительный шаг, но работает, тем не менее.
Манатакс
5
и если вы смешали строку и число и хотите, чтобы они оба были отсортированы, используйте «порядок по столбцу * 1, столбец»
Hayden Thring
1
@superphonic: результат будет decimal.
Юрген д
70

Другой способ, не используя ни одного актера.

(Для людей, которые используют JPA 2.0, где не разрешается кастинг)

select col from yourtable
order by length(col),col

РЕДАКТИРОВАТЬ: работает только для натуральных чисел

Velter
источник
9
это хорошо, это работало со столбцом, который также содержит как int, так и строку
Sruit A.Suk
1
Это не будет работать во всех случаях. Вверху головы, случаи, которые не будут работать, представляют собой смеси целых чисел; отрицательные числа, числа с ведущими нулями, числа с дробями и слова и цифры вместе.
WonderWorker
3
отличное решение без каких-либо типов кастинга и жонглирования, +1
Максим Лузик
казалось, не работает с первого взгляда, но это сработало! Спасибо!
try2fly.b4ucry
19

Еще один и простой способ

ORDER BY ABS(column_name)

Парт Соланки
источник
17

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

DECLARE @tmp TABLE (ID VARCHAR(50));
INSERT INTO @tmp VALUES ('XYZ300');
INSERT INTO @tmp VALUES ('XYZ1002');
INSERT INTO @tmp VALUES ('106');
INSERT INTO @tmp VALUES ('206');
INSERT INTO @tmp VALUES ('1002');
INSERT INTO @tmp VALUES ('J206');
INSERT INTO @tmp VALUES ('J1002');

SELECT ID, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END) IsNum
FROM @tmp
ORDER BY IsNum, LEN(ID), ID;

Полученные результаты

ID
------------------------
106
206
1002
J206
J1002
XYZ300
XYZ1002

Надеюсь это поможет

Losbear
источник
Вы можете просто использовать 1 - ISNUMERIC(ID)вместо, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)чтобы изменить 0 на 1 и наоборот.
С.Серпушан
7

Это работает для меня.

select * from tablename
order by cast(columnname as int) asc
Патрик де Гусман
источник
можешь объяснить почему?
Славик
самый простой ответ, который делает именно то, что нужно, приведёт строку к int, затем упорядочит по этому int в порядке возрастания, ничего
лишнего
4

Еще один способ конвертировать.

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

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( stringfield ) ) , stringfield ) 

или упорядочить по части поля что-то вроде «ensymbols13 », «ensymbols1222» и т. д.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 
shukshin.ivan
источник
2

Я искал также поля сортировки, которые имеют буквенный префикс. Вот что я нашел решение. Это может помочь тем, кто ищет такое же решение.

Значения поля:

FL01,FL02,FL03,FL04,FL05,...FL100,...FL123456789

select SUBSTRING(field,3,9) as field from table order by SUBSTRING(field,3,10)*1 desc

SUBSTRING(field,3,9) я поставил 9, потому что 9 достаточно для меня, чтобы держать максимум 9 цифр целочисленных значений.

Таким образом, результат будет 123456789 123456788 123456787 ... 100 99 ... 2 1

user2400083
источник
2

Это будет обрабатывать отрицательные числа, дроби, строки, все:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;
эмир
источник
2

Это может помочь тем, кто ищет такое же решение.

select * from tablename ORDER BY ABS(column_name)
Самир Лахани
источник
0

Если вы используете AdonisJS и имеете смешанные идентификаторы, такие как ABC-202, ABC-201 ..., вы можете объединить необработанные запросы с Query Builder и реализовать решение, описанное выше ( https://stackoverflow.com/a/25061144/4040835 ) следующим образом:

const sortField =
  'membership_id'
const sortDirection =
  'asc'
const subquery = UserProfile.query()
  .select(
    'user_profiles.id',
    'user_profiles.user_id',
    'user_profiles.membership_id',
    'user_profiles.first_name',
    'user_profiles.middle_name',
    'user_profiles.last_name',
    'user_profiles.mobile_number',
    'countries.citizenship',
    'states.name as state_of_origin',
    'user_profiles.gender',
    'user_profiles.created_at',
    'user_profiles.updated_at'
  )
  .leftJoin(
    'users',
    'user_profiles.user_id',
    'users.id'
  )
  .leftJoin(
    'countries',
    'user_profiles.nationality',
    'countries.id'
  )
  .leftJoin(
    'states',
    'user_profiles.state_of_origin',
    'states.id'
  )
  .orderByRaw(
    `SUBSTRING(:sortField:,3,15)*1 ${sortDirection}`,
    {
      sortField: sortField,
    }
  )
  .paginate(
    page,
    per_page
  )

ПРИМЕЧАНИЯ: В этой строке: SUBSTRING(:sortField:,3,15)*1 ${sortDirection},

  1. «3» обозначает порядковый номер последнего нецифрового символа перед цифрами. Если ваш смешанный идентификатор «ABC-123», ваш индекс будет 4.
  2. «15» используется для определения максимально возможного числа цифр после дефиса.
  3. «1» выполняет математическую операцию с подстрокой, которая эффективно приводит подстроку к числу.

Ссылка 1: Вы можете узнать больше о привязках параметров в необработанных запросах здесь: https://knexjs.org/#Raw-Bindings Ссылка 2: Adonis Raw Queries: https://adonisjs.com/docs/4.1/query-builder# _raw_queries

Ndianabasi
источник
-3

Измените ваше поле на INT вместо VARCHAR.

Я не могу сделать их INT из-за некоторых других обстоятельств.

Затем исправьте обстоятельства в первую очередь. В противном случае вы работаете вокруг реальной основной проблемы. Использование MySQL CAST является опцией, но она маскирует вашу плохую схему, которая должна быть исправлена.

лощина
источник