关于数据库百分数排序(包含字符串截取,指定字符查找,类型转换)

需求:

在profit(收益)表中包含一列 ‘rate(费率)’为百分比,数据类型为varchar,插入的数据为百分数(即xx.xx%)。要求按照百分比的大小排序,数据库为oracle。

分析:

以升序为例,该需求中rate字段为varcahr类型,因此直接排序会出现“1%->10%->11%->2%->3%”的情况,显然不是我们想要的结果。
所以我们需要对该列数据查询时进行数据类型转换,转换成 number 类型;在oracle中提供了两个将字符串类型转换为数字类型的方式:
   1、TO_NUMBER(COLUMN)  将某一列转换为数字类型。
          2、CAST(COLUMN AS NUMBER(10,2)) 将某一列转换为其他类型,此处为数字,只要条件满足可以转换为其他任意类型。
不过,经过测试,这样直接进行数据类型转换后排序,是不可行的,会报错:该列不是有效的数字,什么原因呢?是因为,rate列中存在“%”,“xx%”不是有效的数字,不能直接转换为number类型。
此时,我们只需要将末尾的“%”去除就得到可以转换为number类型的数字,也就我们要截取字符串,将“%”前面的数据截取出来。而在oracle中提供了 substr 方法用来截取字符串:
   语法: 
      substr( string, start_position, [ length ] )
      其中string为字符串,start_position为起始位置,length为截取长度;
      其中start_position为负数的时起始位置从字符串末尾开始算起。 length可省略,而length省略时返回start_position位置后面的所有字符
看到这里,就发现 substr 方法中只能往后截取,而不能从后往前截取。另外,我们需要的是“%”前面的所有字符的,但其长度是未知的,因此就用到了另外一个方法instr,instr方法会返回指定字符出现的位置。即指定字符查找:
    语法:
        instr(string1,string2[,start_position[,nth_appearence]])
        string1:要在此字符串中查找。
        string2:要在string1中查找的字符串。
        start_position:从string1开始查找的位置。可选,默认为1,正数时,从左到右检索,负数时,从右到左检索。(此处与substr相同,即为负的时候只是起始位置从右开始算)
        nth_appearence:查找第几次出现string2。可选,默认为1,不能为负。
这样,我们可以使用instr查找“%”出现的位置,也就是该列数据的最后一个字符位置索引,用索引减1,得到该列数据去除百分号后的字符长度,也就是我们需要截取字符串的长度,截取的字符串为:substr(rate, 0,instr(rate,'%')-1),然后将它转化为number类型,并排序就OK了!
最后我们得到sql语句:
    select * from profit  order by   CAST(substr(rate  , 0,instr(rate  ,'%')-1) AS number(10,2))或
    select * from profit  order by   to_number(substr(rate  , 0,instr(rate  ,'%')-1))

总结:

实际开发中这样的情况比较少,因为“%”这个东西,可以直接在前端加的,数据库里面只需要存储number类型的数据就可了。但也存在其他类似的情况,例如:某公司的员工编号:序号+M,序号+MX。。。类似的情况还是有的。
另外,如果字母在前面那么的话更为简单,因为只需要从字母后一位开始,截取字母后面的所有就可以直接转换类型排序了。
    原文作者:StevenX
    原文地址: https://segmentfault.com/a/1190000006791916
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞