1. 默认情况下,ORDER BY会做升序排列,因此ASC子句是可选的。可以通过DESC执行降序排列。可以再ORDER BY子句中列出不同的排序列,逗号分隔。

一般而言,可以根据一个没有被包含在SELECT列中的列来排序,但是必须明确地指定列名。但是当查询语句中含有GROUP BY或者DISTINCT,那么不能按照SELECT列表之外的列进行排序。该问题可参考《小白学习MySQL - only_full_group_by的校验规则》。

2. 依据子串排序

按照职位字段后3个字符进行排序,

DB2、MySQL、Oracle、PG,

select ename,job
  from emp
 order by substr(job,length(job)-2);

SQL Server,第三个参数,既可以是2,还可以大于2,

select ename,job
  from emp
 order by substring(job,len((job)-2,2);

3. 如果字段混合了字母和数字,其中按照字母或者数字进行排序,例如,

create view V
    as
select ename||' '||deptno as data
  from emp;

使用translate函数和replace函数删除每一行的数字或者字符,即可按照剩余的部分排序。

需求按照ename或者deptno进行排序,

Oracle、PG,按照deptno排序,

select data
 from V
 order by replace(data,
               replace(
             translate(data, '0123456789','##########','#',''),'');

按照ename排序,

select data
  from V
 order by replace(
               translate(data,'0123456789','##########','#','');

DB2,按照deptno排序,

select *
  from (
select ename||' '||cast(deptno as char(2)) as data
  from emp
          ) v
 order by replace(data,
               replace(
             translate(data,'##########','01234567890',),'#',''),'');

按照ename排序,

select *
  from (
select ename||' '||cast(deptno as char(2)) as data
  from emp
          ) v
 order by replace(data,
             translate(data,'##########','01234567890',),'#','');

MySQL和SQL Server不支持translate函数。

4. NULL的排序

DB2、MySQL、PG和SQL Server,需要增加辅助列,

非Null值按照comm升序排列,全部Null值放到最后,删除desc,则放到最前,

select ename, sal, comm
  from (
select ename, sal, comm,
          case when comm is null then 0 else 1 end as is_null
  from emp
          ) x
 order by is_null desc, comm;

Oracle,提供了特殊语法,无需考虑非Null值的排序方式,

非Null值comm升序排列,全部Null值放到最后,

select ename, sal, comm
  from emp
 order by comm nulls last;

非Null值comm升序排列,全部Null值放到最前,

select ename, sal, comm
  from emp
 order by comm nulls first;

5. 依据条件逻辑动态调整排序项

例如,如果job等于salesman,就需要按照comm排序,否则,就按照sal排序,此时用到case...when...子句,

select ename, sal, job, comm
  from emp
 order by case when job='SALESMAN' then comm else sal end;

或者,

select ename, sal, job, comm,
          case when job='SALESMAN' then comm else sal end as ordered
  from emp
 order by 5;