Рядок порядку 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

Як я можу зробити так, щоб він відображався впорядкованим по числу у порядку зростання


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

BTW 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,
коль

1
@superphonic: Результат буде decimal.
juergen d

70

Інший спосіб, без використання жодної ролі.

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

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

EDIT: працює лише для натуральних чисел


9
це добре, цей працював із стовпцем, який також містить int та string
Sruit A.Suk

1
Це не спрацює у всіх випадках. У верхній частині голови випадки, які не спрацюють, - це суміші з цілих чисел; від’ємні числа, числа з провідними нулями, числа з дробами та словами та цифрами у поєднанні.
WonderWorker

3
чудове рішення без будь-яких типів кастингу та жонглювання, +1
Максим Лузик

З першого погляду, здавалося, не працює, але це спрацювало! Дякую!
try2fly.b4ucry


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

Сподіваюся, це допомагає


Ви можете просто використовувати 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 ) 

або замовити за частиною поля щось на зразок 'tensymbols13', 'tensymbols1222' тощо.

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

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


2

Це буде обробляти негативні числа, дроби, рядки, все:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;


0

Якщо ви використовуєте AdonisJS і маєте змішані ідентифікатори, такі як ABC-202, ABC-201 ..., ви можете комбінувати необроблені запити з Builder Query і реалізувати рішення вище ( 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 Ref 2: Adonis Raw Queries: https://adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

Змініть поле, щоб воно було INT, а не VARCHAR.

Я не можу зробити їх INT через якісь інші залежні обставини.

Потім спочатку зафіксуйте залежні обставини. Інакше ви працюєте над справжньою базовою проблемою. Використання MySQL CAST - це варіант, але він маскує вашу погану схему, яку слід виправити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.