记一次mysql的教训

新知识

字符串的字典序

字典序(dictionary order),又称 字母序(alphabetical order),原意是表示英文单词在字典中的先后顺序,在计算机领域中扩展成两个任意字符串的大小关系。
在Java语言中,**System.out.println(“ah1x”.compareTo(“ahb”));**会输出 -49−49,这个数是两个字符串第一个不一样的位置的两个字符的 ASCII 值之差,如果小于零则说明第一个字符串小于第二个字符串。
除此之外,大多数语言也都有对应的字符串比较方法,而背后的核心都是字符串的字典序。理解并掌握这个重要的概念,对今后计算机专业课程的学习和程序开发都至关重要。

场景复现

问题:我有一个名为hexcodetable的MySQL表,只有一个名为VARCHAR(100)的名为hexcode的列。该表包含所有十六进制颜色代码。这些行填充为六个字符的十六进制数字,后跟#。例如,#25F412。我们如何对从最黑到最白的所有行进行排序,使得第一行为#000000,第二行为#000001,最后一行为#FFFFFF?请注意,我不一定要进行数字排序。
答案:按十六进制值进行数字排序。

Select hexcode from hexcodetable order by Conv(substring(hexcode,2,6),16,10)

详解

  • MySQL conv()函数
    CONV(N,from_base,to_base)
    所述CONV()函数的目的是在基数之间进行转换。该函数返回值N从from_base到to_base转换的字符串。最小基数值是2,最大值为36。如果任一参数为NULL,则该函数返回NULL。考虑下面的例子,其中数字 5 将从基数16转为基数2

        mysql> SELECT CONV(5,16,2);
      +---------------------------------------------------------+
      | CONV(5,16,2)                                            |
      +---------------------------------------------------------+
      | 101                                                     |
      +---------------------------------------------------------+
    1 row in set (0.00 sec)
    

    延伸bug

    这条sql里面有个坑就是,有时按照某个字段的大小排序(或是比大小)发现排序有点错乱。后来才发现,是我们想当然地把对字符串字段当成数字并按照其大小排序(或是比大小),结果肯定不会是你想要的结果。
    这时候需要把字符串转成数字再排序,最简单的办法就是在字段后面加上+0。

  • 排序:
    例:
    方法一:ORDER BY ‘123’+0;(首推)
    方法二:ORDER BY CAST(‘123’ AS SIGNED);
    方法三:ORDER BY CONVERT(‘123’,SIGNED);

正确解决方案

Select hexcode from hexcodetable order by Conv(substring(hexcode,2,6)+0,16,10)

相似问题

MySQL中怎么对varchar类型排序问题:转载自【https://www.cnblogs.com/dengyungao/p/8324590.html】

asc 升级

desc降序

在mysql默认order by 只对数字与日期类型可以排序,但对于varchar字符型类型排序好像没有用了,下面我来给各位同学介绍varchar类型排序问题如何解决。

今天在对国家电话号码表进行排序的时候发现了一个有趣的问题,我想让isdcode字段按照由小到大的顺序排序,于是乎我是这样写的

SELECT * FROM gb_country_isdcode ORDER BY isdcode asc

结果如下,发现竟然不是我想要的结果,asc排序是对的呀,于是乎我找呀找,找呀找,终于找到原因了;

isdcode是varcher类型的,如果排序的直接用asc显然是不行的,必须将他转换成int类型然后就可以正常排序了,只要isdcode + 0就可以了

于是乎这样写

SELECT * FROM gb_country_isdcode ORDER BY (isdcode+0) asc

好像是想要的那种数据比较大小的了呀。。可是为什么+0就好了呢?原来,+0后就转换INT类型排序了。这样就可以按照大小排序了。

如果不是电话而是汉字怎么办,汉字排序我们只要进行简单转换即可排序了。

在mysql中使用order by对存储了中文信息的字段,默认出来的结果并不是按汉字拼音的顺序来排序,要想按汉字的拼音来排序,需要把数据库的字符集设置为UTF8,然后在order by 时候强制把该字段信息转换成GBK,这样出来的结果就是按拼音顺序排序的。例如:

SELECT * FROM table_name ORDER BY CONVERT(column_name USING gbk);

在mysql中试了一下,结果很令人满意。

结论是:查询的时候,通过convert函数,把查询出来的数据使用的字符集gb2312编码就可以了,然后使用convert之后的中文排序。但是如果真的去把表中字段的字符集改成gb2312,又会涉及到很多编码的问题,页面传值啊,从数据库中存取啊,很麻烦。只要在查询的时候,指定一下字符集,并不是真的把物理字段改成gb2312,很简单。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!