SQL 根据字符串里的数字排序,你希望根据字符串里的数字对结果集进行排序,考虑下面的视图。
SQL 根据字符串里的数字排序 问题描述
你希望根据字符串里的数字对结果集进行排序,考虑下面的视图。
下面是上述视图返回的数据。
以上数据包括员工名字、员工编号和部门名称三部分数据,你希望按照中间的员工编号对该数据进行排序。
SQL 根据字符串里的数字排序 解决方案
下面的每一种解决方案都使用了各个数据库特有的函数和语法,但方法(利用内置函数 REPLACE
和 TRANSLATE
)却是相同的。基本思路都是使用 REPLACE
和 TRANSLATE
函数删除字符串里的非数字字符,只留下用于排序的数字。
DB2
使用内置函数 REPLACE
和 TRANSLATE
提取字符串里的数字,并按照数字排序。
Oracle
使用内置函数 REPLACE
和 TRANSLATE
提取字符串里的数字,并按照数字排序。
PostgreSQL
使用内置函数 REPLACE
和 TRANSLATE
提取字符串里的数字,并按照数字排序。
MySQL 和 SQL Server
在写作本书时,这两种数据库尚不支持 TRANSLATE
函数。
SQL 根据字符串里的数字排序 扩展知识
视图 V
只是为了提供演示本实例解决方案的数据。该视图只是简单地把 EMP
表的一些列串联起来。上述解决方案展示了如何以串联后的文本作为输入数据,并按照嵌入其中的员工编号进行排序。
各个解决方案的 ORDER BY
子句虽然看起来有点吓人,但效果不错。如果我们一段一段地仔细阅读的话,就会发现它其实不难理解。为了按照字符串里的数字排序,最简单的办法就是删除所有的非数字字符。删除非数字字符后,把数字字符变成数值类型,并进行排序。在开始解释每一次函数调用之前,我们要先理解各个函数被调用的次序。先从最内层的 TRANSLATE
函数调用(每个解决方案的第 8 行)开始,我们可以看到:
(1) TRANSLATE
函数(第 8 行)被调用,把执行结果传递给;
(2) REPLACE
函数(第 7 行),并把执行结果传递给;
(3) TRANSLATE
函数(第 6 行),并把执行结果传递给;
(4) REPLACE
函数(第 5 行),其执行结果被返回,最后;
(5) 转换为数值类型。
第一步是把数字替换为一个特别的字符,它和去掉数字后字符串里剩下的字符都不相同。本例中我选择了 #
,并使用 TRANSLATE
函数把所有的数字都替换成 #
。例如,下面的查询左边显示的是原来的字符串,右边显示的是第一次转换后得到的结果。
TRANSLATE
函数找到每个字符串里的数字字符,并逐一替换为 #
。转换后字符串被传递到 REPLACE
函数(第 7 行),它会删除所有的 #
。
然后,上述结果再一次被传递给 TRANSLATE
函数,但这次是本解决方案第二次(最外层)调用 TRANSLATE
函数。该 TRANSLATE
函数在原来的字符串中搜索和 TMP
相匹配的字符。如果找到的话,就把它们都替换成 #
。这一转换使得所有非数字字符能够被当作单一字符来处理(因为它们都被替换成了相同的字符)。
接下来,通过调用 REPLACE
函数(第 5 行)删除所有的 #
,只留下数字字符。
最后,使用数据库管理系统中合适的函数(通常是 CAST
)把 TMP
转换为数值类型(第 4 行),结果如下所示。
当编写类似这样的查询语句时,不妨把写好的表达式放入 SELECT
列表里试着执行一下,这会非常有用。因为我们能很容易看到中间结果,直到得出最终的解决方案。然而,因为本实例的重点是对结果集进行排序,所以最终仍需要把所有的函数调用都放进 ORDER BY
子句里。
最后值得注意的是,本例的视图数据包含 3 个字段,其中只有一个字段是数字。如果有多个数字字段,就需要将它们拼接成一个数字,然后再排序。