在SQL中对包含数字的字符串列进行排序?

时间:2011-02-08 23:00:43

标签: sql mysql sql-order-by

我正在尝试对字符串列(包含数字)进行排序。

// 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 个答案:

答案 0 :(得分:36)

继续假设它始终是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)

答案 1 :(得分:2)

你可以试试这个:

ORDER BY CASE
  WHEN ISNUMERIC(column) THEN cast(column as int) 
  else ascii(column[1,1]) 
end

答案 2 :(得分:1)

查看MySQL CAST / Convert函数。

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

修改 我读到了:

  

我正在尝试排序字符串列   (包含数字)。

...但只是看了一下结果集。 a实际上也是内容的一部分吗?如果是这样,您可以使用MID之类的函数来仅提取数值并进行转换。

但如果所有行只包含a而没有变体,那么您可以省略它......

答案 3 :(得分:0)

另一种选择可能是在数字的左边用空格填充字符串(即在单词和数字之间添加空格)并使用生成的字符串进行排序,如下所示:

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

假设该字符串的格式为'word后跟空格后跟数字',并且该数字被假定为非负数(或者它将排序不正确)。硬编码的20是任意选择的,应该是字符串数字部分的最大可能长度。

答案 4 :(得分:0)

在这里,我找到了另一个解决方案,使用转换

进行以下查询
select * from tablename where columnname like '%a%' order by Convert(smallint,Replace(columnname,'a',''))