Сортировка строки столбца, содержащего числа в SQL? - PullRequest
25 голосов
/ 09 февраля 2011

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

// 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 , илиЯ должен манипулировать набором результатов на уровне приложения?

Ответы [ 5 ]

36 голосов
/ 09 февраля 2011

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

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

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

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


РЕДАКТИРОВАТЬ Проверено на работу:

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)
2 голосов
/ 19 декабря 2013

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

ORDER BY CASE
  WHEN ISNUMERIC(column) THEN cast(column as int) 
  else ascii(column[1,1]) 
end
1 голос
/ 09 февраля 2011

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

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

Edit: Я читаю:

Я пытаюсь отсортировать столбец строки (содержит цифры).

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

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

0 голосов
/ 19 июня 2013

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

select * from tablename where columnname like '%a%' order by Convert(smallint,Replace(columnname,'a',''))
0 голосов
/ 09 февраля 2011

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

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

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

...