我正在尝试对字符串列(包含数字)进行排序。
// 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 :(得分: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',''))