2011-02-08 2 views
24

Я пытаюсь сортировать строку колонку (, содержащую номера).Сортировка строкового столбца, содержащего числа в SQL?

// SELECT `name` FROM `mytable` ORDER BY `name` ASC 
+----------+ 
+-- name --+ 
+----------+ 
+-- a 1 ---+ 
+-- a 12 --+ 
+-- a 2 ---+ 
+-- a 3 ---+ 

Вы видите естественный алгоритм сортировки Mysql является размещением a 12 после a 1 (, который нормален для большинства приложений), но у меня есть уникальные потребности, поэтому я хочу, результат должен быть отсортирован, как это.

+----------+ 
+-- name --+ 
+----------+ 
+-- a 1 ---+ 
+-- a 2 ---+ 
+-- a 3 ---+ 
+-- a 12 --+ 

Можно с только SQL, или я должен манипулировать результатом набора на уровне приложений?

+0

алфавитный префикс всегда постоянная длина для всех строк? –

+0

Нет, это регулярная строка, которая иногда повторяется. – Ish

+2

Итак, что-то вроде 'order by left (name, 1), cast (SUBSTRING (name, 2) as int)' не будет работать тогда. Можете ли вы предоставить несколько более разнообразных данных, которые иллюстрируют ваши конкретные потребности? –

ответ

36

Переход на предположения это всегда WORD_space_NUMBER это должно работать:

SELECT * 
FROM  table 
ORDER BY CAST(SUBSTRING(column,LOCATE(' ',column)+1) AS SIGNED) 

Использование POSITION, чтобы найти место, SUBSTRING, чтобы захватить номер после него и CAST, чтобы сделать его сопоставимым.

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


EDIT Проверенная на работу:

mysql> INSERT INTO t (st) VALUES ('a 1'),('a 12'),('a 6'),('a 11'); 
Query OK, 4 rows affected (0.00 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> SELECT * FROM t ORDER BY st; 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 4 | a 11 | 
| 2 | a 12 | 
| 3 | a 6 | 
+----+------+ 
4 rows in set (0.00 sec) 

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 3 | a 6 | 
| 4 | a 11 | 
| 2 | a 12 | 
+----+------+ 

mysql> INSERT INTO t (st) VALUES ('b 1'),('b 12'),('b 6'),('b 11'); 
Query OK, 4 rows affected (0.00 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 5 | b 1 | 
| 3 | a 6 | 
| 7 | b 6 | 
| 4 | a 11 | 
| 8 | b 11 | 
| 2 | a 12 | 
| 6 | b 12 | 
+----+------+ 
8 rows in set (0.00 sec) 

mysql> SELECT * FROM t ORDER BY LEFT(st,LOCATE(' ',st)), CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 3 | a 6 | 
| 4 | a 11 | 
| 2 | a 12 | 
| 5 | b 1 | 
| 7 | b 6 | 
| 8 | b 11 | 
| 6 | b 12 | 
+----+------+ 
8 rows in set (0.00 sec) 

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

Редактировать SUBSTRING_INDEX сделает его немного более удобным для чтения.

ORDER BY SUBSTRING_INDEX(st, " ", 1) ASC, CAST(SUBSTRING_INDEX(st, " ", -1) AS SIGNED) 
+0

У вас есть человек ... спасибо миллион – Ish

+0

@ish: Нет проблем. Вы также можете добавить 'LEFT (столбец, LOCATE ('', column))' в порядке, чтобы сгруппировать его буквой (-ами), а затем цифры. –

+0

спасибо за дополнительные опции :), Ваше оригинальное решение послужило моей цели. И я узнал о возможностях MySQL «CAST» ... ура – Ish

1

Посмотрите на функции MySQL CAST/Convert.

SELECT name FROM mytable ORDER BY CAST(name AS INTEGER) ASC; 

Edit: Я читаю:

Я пытаюсь сортировать строку, столбец (содержащие номера).

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

Но если все строки содержат только a без изменения, вы можете также опустить его ...

+0

получил ошибку mysql 'правильный синтаксис для использования рядом с« INTEGER »ASC LIMIT 0, 30' – Ish

+0

@Ish: Из-за того же, о чем я забыл. При использовании CAST/CONVERT используйте SIGNED/UNSIGNED. –

0

Другим вариантом может быть прокладка строки с пробелами слева от номера (т.добавить пробелы между словом и числом) и использовать полученную строку для сортировки, comething как это:

ORDER BY INSERT(
    column, 
    LOCATE(' ', column), 
    0, 
    SPACES(20 - LENGTH(column) + LOCATE(' ', column)) 
) 

Предполагается, что строка иметь «слова с последующим пробелом (ами) с последующим номером» рисунка, и число считается неотрицательным (или оно будет сортироваться некорректно). Hardcoded 20 выбирается произвольно и должен быть максимально возможной длиной номера части строки.

0

Здесь я нашел другое решение, с помощью следующего запроса с помощью Преобразовать

select * from tablename where columnname like '%a%' order by Convert(smallint,Replace(columnname,'a','')) 
1

Вы можете попробовать это:

ORDER BY CASE 
    WHEN ISNUMERIC(column) THEN cast(column as int) 
    else ascii(column[1,1]) 
end 
Смежные вопросы