SQL 排序时对Null值的处理

SQL 排序时对Null值的处理,你想按照 EMP 表的 COMM 列对查询结果进行排序,但该字段可能为 Null。因此,你需要想个办法来指定是否应该将 Null 值排到后面。

SQL 排序时对Null值的处理 问题

你想按照 EMP 表的 COMM 列对查询结果进行排序,但该字段可能为 Null。因此,你需要想个办法来指定是否应该将 Null 值排到后面。

ENAME             SAL       COMM
---------- ---------- ----------
TURNER           1500          0
ALLEN            1600        300
WARD             1250        500
MARTIN           1250       1400
SMITH             800
JONES            2975
JAMES             950
MILLER           1300
FORD             3000
ADAMS            1100
BLAKE            2850
CLARK            2450
SCOTT            3000
KING             5000

或者你希望把 Null 值放在前面。

ENAME             SAL COMM
---------- ---------- ----------
SMITH             800
JONES            2975
CLARK            2450
BLAKE            2850
SCOTT            3000
KING             5000
JAMES             950
MILLER           1300
FORD             3000
ADAMS            1100
MARTIN           1250       1400
WARD             1250        500
ALLEN            1600        300
TURNER           1500          0

SQL 排序时对Null值的处理 解决方案

根据你希望的排序方式(以及你所使用的数据库管理系统如何处理 Null 值排序问题),你能够对可能为 Null 的列进行升序排列或者降序排列。

select ename,sal,comm
  from emp
 order by 3
 
select ename,sal,comm
  from emp
 order by 3 desc

这个解决方案表明,如果一个可能为 Null 的列含有非 Null 值,它们也会相应地被升序排列或降序排列;这与你的直觉可能相反。但是,如果你希望采用与非 Null 值列不同的方式来排列 Null 值,例如,你可能想把非 Null 值以升序排列或降序排列,而把全部 Null 值都放到最后面,那么你就要使用 CASE 表达式来动态调整排序项。

DB2、MySQLPostgreSQLSQL Server

使用 CASE 表达式标记 Null 值。该标记有两种可能的取值:一种代表 Null 值,另一种代表非 Null 值。一旦你做好了标记,只要简单地把它放进 ORDER BY 子句就行了。这样一来,你就能在不影响非 Null 值的情况下,方便地调整 Null 值的位置了。

/* 非Null值COMM升序排列,全部Null值放到最后面 */
 
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_nulldesc,comm
ENAME    SAL       COMM
------ ----- ----------
TURNER  1500          0
ALLEN   1600        300
WARD    1250        500
MARTIN  1250       1400
SMITH    800
JONES   2975
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
BLAKE   2850
CLARK   2450
SCOTT   3000
KING    5000
/* 非Null值COMM降序排列,全部Null值放到最后面 */

 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_nulldesc,commdesc
ENAME    SAL       COMM
------ ----- ----------
MARTIN  1250       1400
WARD    1250        500
ALLEN   1600        300
TURNER  1500          0
SMITH    800
JONES   2975
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
BLAKE   2850
CLARK   2450
SCOTT   3000
KING    5000
/* 非Null值COMM升序排列,全部Null值放到最前面 */

 selectename,sal,comm
   from (
 selectename,sal,comm,
        case when comm is null then 0 else 1 end as is_null
   from emp
        )x
  order by is_null,comm
ENAME    SAL       COMM
------ ----- ----------
SMITH    800
JONES   2975
CLARK   2450
BLAKE   2850
SCOTT   3000
KING    5000
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
TURNER  1500          0
ALLEN   1600        300
WARD    1250        500
MARTIN  1250       1400
/* 非Null值COMM降序排列,全部Null值放到最前面 */

 selectename,sal,comm
   from (
 selectename,sal,comm,
        case when comm is null then 0 else 1 end as is_null
   from emp
        )x
   order by is_null,comm desc
ENAME    SAL       COMM
------ ----- ----------
SMITH    800
JONES   2975
CLARK   2450
BLAKE   2850
SCOTT   3000
KING    5000
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
MARTIN  1250       1400
WARD    1250        500
ALLEN   1600        300
TURNER  1500          0

Oracle

如果你使用的是 Oracle 8i 或者更早的版本,可以使用上述针对其他平台的解决方案。如果使用的是 Oracle 9i 及后续版本,则能使用针对 ORDER BY 子句的扩展语法 NULLS FIRSTNULLS LAST 来决定 Null 值应该排到前面还是后面,而无须考虑非 Null 值的排序方式。

/* 非Null值COMM升序排列,全部Null值放到最后面 */
select ename,sal,comm
  from emp
order by comm nulls last
ENAME    SAL       COMM
------ ----- ----------
TURNER  1500          0
ALLEN   1600        300
WARD    1250        500
MARTIN  1250       1400
SMITH    800
JONES   2975
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
BLAKE   2850
CLARK   2450
SCOTT   3000
KING    5000
/* 非Null值COMM降序排列,全部Null值放到最后面 */

select ename,sal,comm
  from emp
order by commdesc nulls last
ENAME    SAL       COMM
------ ----- ----------
MARTIN  1250       1400
WARD    1250        500
ALLEN   1600        300
TURNER  1500          0
SMITH    800
JONES   2975
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
BLAKE   2850
CLARK   2450
SCOTT   3000
KING    5000
/* 非Null值COMM升序排列,全部Null值放到最前面 */

select ename,sal,comm
  from emp
order by comm nulls first
ENAME    SAL       COMM
------ ----- ----------
SMITH    800
JONES   2975
CLARK   2450
BLAKE   2850
SCOTT   3000
KING    5000
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
TURNER  1500          0
ALLEN   1600        300
WARD    1250        500
MARTIN  1250       1400
/* 非Null值COMM降序排列,全部Null值放到最前面 */

select ename,sal,comm
  from emp
order by commdesc nulls first
ENAME    SAL       COMM
------ ----- ----------
SMITH    800
JONES   2975
CLARK   2450
BLAKE   2850
SCOTT   3000
KING    5000
JAMES    950
MILLER  1300
FORD    3000
ADAMS   1100
MARTIN  1250       1400
WARD    1250        500
ALLEN   1600        300
TURNER  1500          0

SQL 排序时对Null值的处理 扩展知识

除非数据库管理系统提供了一种方式,它能够让你在无须修改非 Null 值数据的情况下方便地把 Null 值排到最前面或者最后面(像 Oracle 那样),否则你就得添加一个辅助列。

辅助列(只存在于查询语句里,而不存在于表中)的目的是,让你能够识别出 Null 值,并控制其排在最前面还是最后面。对于非 Oracle 解决方案的查询语句,其内嵌视图 X 会返回如下结果集。

select ename,sal,comm,
       case when comm is null then 0 else 1 end as is_null
  from emp
ENAME    SAL       COMM    IS_NULL
------ ----- ---------- ----------
SMITH    800                     0
ALLEN   1600        300          1
WARD    1250        500          1
JONES   2975                     0
MARTIN  1250       1400          1
BLAKE   2850                     0
CLARK   2450                     0
SCOTT   3000                     0
KING    5000                     0
TURNER  1500          0          1
ADAMS   1100                     0
JAMES    950                     0
FORD    3000                     0
MILLER  1300                     0

通过使用 IS_NULL 返回的值,你就能在不影响 COMM 排序的情况下,轻而易举地把全部 Null 值放到最前面或者最后面。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程