在MySQL中以数字方式对varchar字段进行排序

wow*_*wow 37 mysql sorting

我有一个number类型的领域varchar.即使它是类型varchar,它也存储带有可选前导零的整数值.排序按字典顺序排序("42"之前"9").如何通过数值("9"以前"42")订购?

目前我使用的查询:

SELECT * FROM table ORDER BY number ASC
Run Code Online (Sandbox Code Playgroud)

bob*_*obs 69

试试这个

SELECT * FROM table_name ORDER BY CAST(field_name as SIGNED INTEGER) ASC
Run Code Online (Sandbox Code Playgroud)

  • 这对于大型数据库是否有效? (3认同)
  • @marcog:正如paxdiable在答案中所提到的,这将是一个性能杀手. (3认同)

pax*_*blo 38

有几种方法可以做到这一点:

  1. 将它们存储为数值而不是字符串.你已经打了折扣,因为你想要保持00100完整的字符串与前导零.
  2. 按字母顺序排序为数字.这将有效,但要注意它是适合大小合适的数据库的性能杀手.每行功能实际上不能很好地扩展.
  3. 添加第三列,该列是字符串和索引的数字等效项.然后使用插入/更新触发器确保在字符串列更改时正确设置.

由于绝大多数数据库的读取频率远远高于写入数据库,因此上述第三个选项会在所有选择中分摊计算成本(在插入/更新时完成).您的选择将非常快,因为他们使用数字列进行排序(并且没有每行功能).

您的插入和更新将会变慢,但这是您支付的价格,说实话,这非常值得付费.

触发器的使用保持了表的ACID属性,因为两列是保持一致的.这是一个众所周知的习惯用法,你通常可以在大多数性能优化中随时间换掉空间.

我们在很多情况下都使用过这种"技巧",例如将原始文件的较低版本的姓氏存储(而不是使用类似的东西insert),识别字符串的长度以查找具有7个字符的所有用户(而不是使用update)等等.

请记住,只要您理解(并减轻)后果,就可以从第三种正常形式恢复性能.

  • 这是WOW的回答.这非常值得付钱 (2认同)

wor*_*mer 29

其实我发现了一些有趣的东西:

SELECT * FROM mytable ORDER BY LPAD(LOWER(mycol), 10,0) DESC
Run Code Online (Sandbox Code Playgroud)

这允许您订购字段,如:

1
2
3
10
A
A1
B2
10A
111
Run Code Online (Sandbox Code Playgroud)


sha*_*nuo 19

SELECT * FROM table ORDER BY number + 0
Run Code Online (Sandbox Code Playgroud)


小智 16

诀窍我刚学会了.将"+0"添加到varchar字段顺序子句:

SELECT * FROM table ORDER BY number+0 ASC
Run Code Online (Sandbox Code Playgroud)

我现在看到上面这个答案.我想知道这是否是字段和整数的类型转换.我没有比较性能.工作得很好.


小智 5

对于具有Er353,ER 280,ER 30等值的表格,ER36默认排序将给出ER280 ER30 ER353 ER36

SELECT fieldname, SUBSTRING(fieldname, 1, 2) AS bcd, 
CONVERT(SUBSTRING(fieldname, 3, 9), UNSIGNED INTEGER) AS num 
FROM table_name
ORDER BY bcd, num;
Run Code Online (Sandbox Code Playgroud)

结果将按此顺序ER30 ER36 ER280 ER353