Mysql 对字符串类型的数字排序

大家好,我是娟姐。

有一次对字符串类型的数字排序,怎么排都排不出想要的效果,后来加了个0轻松解决。

最近又遇到了字符串类型的数字排序,可是在开会的时候,我却记不清对于排序字段为null的数据到底是排在最前面呢,还是排在最后面呢?后来,干脆说不是排在后面就是排在前面...

开完会赶紧测试一下。

一、int型数字排序

随便建了一张表,表名为fddd,其中age为int型字段,name为varchar型字段。

未排序的数据

这里使用age进行排序,age有的为null,不写排序顺序,默认升序。

select * from fddd  order by age;

使用age排序后,为null的数据被排在了最前面。

使用age排序后

二、字符串型数字排序

还是针对这张表,使用name进行排序,希望能够按照数字的大小进行升序排序,首字母为字母的忽略不计。

select * from fddd  order by name;

排序的结果,如下图所示,name为null的排在了最前面,空字符串次之,首字母是特殊符号的字符串排在了数字的前面,最后才是对字符串的排序。

使用varchar类型的name进行排序

如果我想按照数字的顺序排序怎么办?没错,就是对字符串加0然后排序。

select * from fddd  order by name+0 ;
select * from fddd  order by name*1 ;

这个排序结果,还是让我挺意外的,null依旧首当其冲排在了最前面,接下来是字符串,空字符串被排在了字母中间,最后才是对首字母为数字的排序,并且按照数字的顺序排列的。

图片

也可以使用函数来达到同样的排序效果:

# CAST(value as type);
# CONVERT(value, type);
# type可以为:浮点数 : DECIMAL ,整数 : SIGNED,无符号整数 : UNSIGNED 
select * from fddd order by cast(name as decimal);
select * from fddd order by convert(name ,decimal);

数据虽然不多,但也可以对比一下它们的性能。

图片

三、Mysql中的字符集和排序规则

在创建数据库的时候,需要选择字符集和排序规则。

图片

字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等等。

字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集、UTF8字符集等等。

字符编码是把字符集 中的 字符 编码 为特定的二进制数据,以便存储在计算机中。编码方式一般就是对二维表的横纵坐标进行变换的算法。

字符集和字符编码都是成对出现的,如ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了对应的字符编码,也统称为编码。

在创建数据库时,我们一般会选择 utf8 字符集,排序规则选择utf8_general_ci。

如果要支持表情符号,就需要选择 utf8mb4。utf8 每个字符最多支持三个字节,utf8mb4 是为了修复 utf8 bug而提出的替代方案,在 utf8mb4 中 每个字符支持 四个字节,所以可以存储表情符号。

utf8_general_ci 中的 ci 是 ‘Case Insensitive’,即大小写不敏感,对A 和 a 是一样的。还有一种 cs 是 ‘Case Sensitive’,即大小写敏感,A和a是不一样的。

四、字符串排序规则

我们都知道,在Mysql中,字符串的排序 是根据 字符串的首字母的ASCII码进行排序的,首字母相同的,则会根据第二个字母排序,以此类推。

在ASCII码中,NULL的顺序排在第一位,对应十进制的0,因此只要是升序排序,NULL字段永远排在第一位。

数字 0 对应的 ASCII 的十进制是 48。

大写字母 A 对应的 ASCII 的十进制是 65,小写字母 a 对应的 ASCII 的十进制是 97。

在上面的sql中对字符串 +0,*1,CAST(value as type),CONVERT(value, type)操作后,发生了什么?让我们用 sql 语句验证下。

select 'adfdf' + 0 , 'adfdf' * 1, cast('adfdf' as decimal),convert('adfdf' ,decimal);
select '1dddd' + 0 , '1dddd' * 1, cast('1dddd' as decimal),convert('1dddd' ,decimal);
select '10他们' + 0 , '10他们' * 1, cast('10他们' as decimal),convert('10他们' ,decimal);
图片
图片
图片

Mysql底层是怎么执行的,还没有研究过。但是通过执行结果,我们可以看出来,这几种写法的结果都一样,都是对字符串的首字母进行了强转,在强转的过程中忽略字符串的存在,只看数字。这样,我们就可以对字符串类型的数字进行排序,并且忽略首字母为字符串的数据了。

每天进步一点点,以上便是此次的整理,希望对你有帮助。

你可能感兴趣的:(Mysql 对字符串类型的数字排序)