我有一个包含数字和字母列'tag'的表格,例如:
1
2
3
4a
4b
10
11
12
20
Z1
当我运行以下查询时,我没有得到所需的顺序:
SELECT * FROM `items` ORDER BY `tag` ASC;
这将输出为(1,11,12,2,20,4a,4b,P1)
然后我在查询中使用“+ 0”或“* 1”找到了一个更好的解决方法:
SELECT * FROM `items` ORDER BY `tag` + 0 ASC;
这将输出为(Z1,1,2,3,4b,4a,10,11,12,20),这只是稍好一点
有没有办法对值进行排序,使它们显示为:
(1,2,3,4a,4b,10,11,12,20,Z1)
我想避免添加订单列,因为我有30,000个项目,标签只是较大类别的子集。
答案 0 :(得分:0)
试试这个:
SELECT * FROM `items` ORDER BY CAST(`tag` as UNSIGNED) ASC;
修改强>
SELECT * FROM items
ORDER BY (tag REGEXP '[0-9]^'),
CASE WHEN tag REGEXP '^[0-9]' THEN tag*1 ELSE tag END;
答案 1 :(得分:0)
似乎您要分隔以数字开头并以字母开头的字符串。 如果是这样,那么试试这个:
SELECT tag, tag*1,(tag REGEXP '^[0-9]') FROM items
ORDER BY (tag REGEXP '^[0-9]') DESC,
tag*1,tag
答案 2 :(得分:0)
更新:这似乎是very non-trivial在MySQL中实现的。即使你确实实现了它,我想它会慢得多。如果您必须按此标记排序,我建议将其分成几列,并将标记列作为这些列的计算串联
您的标签格式为:可选字母集,整数,另一组可选字母。要正确地订购这些,你将要提取标签的每个部分,这样你就可以将字母比作字符串,将数字作为整数进行比较。
SQLFiddle已关闭所以以下是问题的SQLServer解决方案,它可能会帮助您(或其他可以提供帮助的人)在MySQL中可视化如何执行此操作,尽管查询将有很大不同。以下a
是tag
。
SELECT a
,CASE WHEN a LIKE '[^0-9]%'
THEN LEFT(a, ISNULL(NULLIF(PATINDEX('%[^0-9][0-9]%', a ),0),LEN(a)))
ELSE ''
END AS StartLetter
,CAST(SUBSTRING(a
,PATINDEX('%[0-9]%', a )
,(LEN(a)+2-PATINDEX('%[0-9]%', REVERSE(a)))-PATINDEX('%[0-9]%', a))
AS INT) AS Number
,SUBSTRING(a
,LEN(a)+2-PATINDEX('%[0-9]%', REVERSE(a) )
,LEN(a)-1) AS EndLetter
FROM @t
ORDER BY STartLetter, Number, EndLetter
产生以下内容(对于您的数据+一些额外的测试数据):
+-----+-------------+--------+-----------+
| a | StartLetter | Number | EndLetter |
+-----+-------------+--------+-----------+
| 1 | | 1 | |
| 2 | | 2 | |
| 3 | | 3 | |
| 4ab | | 4 | ab |
| 4b | | 4 | b |
| 10 | | 10 | |
| 11 | | 11 | |
| 12 | | 12 | |
| 20 | | 20 | |
| B1 | B | 1 | |
| B22 | B | 22 | |
| BA2 | BA | 2 | |
| Z1 | Z | 1 | |
| Z2b | Z | 2 | b |
| Z3 | Z | 3 | |
+-----+-------------+--------+-----------+
尽管如此,考虑到订购数据有多复杂,我认为您需要重新考虑您首先按专栏订购的决定。