SQL中的Null值处理
在日常的开发中,遇到需要处理 Null 值的场景还是蛮常见的。比如,查询某个字段包含 Null 值的记录、在展示的时候将 Null 值转为其它值、聚合包含 Null 值的列等。
今天就和大家聊聊在 MySQL 中处理 Null 值时需要注意的点,本文包含以下内容:
- 查找 Null 值
- 将 Null 值转为实际值
- 在排序中对 Null 值的处理
- 计算非 Null 值的数量
- 聚合 Null 列
1 查找 Null 值
查找 Null 值不能使用 “=”,而应该使用“is Null”。同理,查找非 Null 值也不能使用 “<>” ,而要使用 “is not Null”。这是初学者容易犯的错误。
比如,查询 emp 表中字段 comm 为 Null 的记录,就这么写 SQL:
SELECT
*
FROM
emp
WHERE comm IS NULL
有时候根据业务需要,我们要找出在 emp 表中没有提成的员工的信息。没有提成可以理解为提成为 0 或者本身就不包含提成,因此查询的条件就应该这么写 comm IS NULL OR comm = 0
。
类似的,在处理字符串类型的字段的时候,我们要找出某个字段没有值的记录。假设该字段叫作 xxx,xxx 允许设置 Null 值。初学者经常犯的错误就是给出的查询条件不完整,要么写成 xxx = ''
,要么写成 xxx is null
,正确的写法是 xxx = '' or xxx is null
,或者是其它变体。
2 将 Null 值转为实际值
有时候做报表展示的时候,我们不希望将 Null 值直接展示出来,而是转为其它值。比如,是数值类型的字段就展示成 0,是字符串类型就展示成空白字符。
使用函数 COALESCE()
可将 Null 值转成其它值,将 emp 表中 comm 列的 Null 值转成 0 就可以这么写:COALESCE(comm,0)
。在 MySQL 中还可以使用 IFNULL(comm,0)
,或者 case when
。
3 处理排序中的 Null 值
如果是使用默认的升序对包含有 Null 值的列做排序,有 Null 值的记录会排在前面,而使用了降序排序,包含了 Null 值的记录才会排在后面。
对于下面这条语句,它的排序结果在它下方。
SELECT
empno,
ename,
comm
FROM
emp
ORDER BY comm
排序结果:
empno ename comm
------ ------ ---------
7369 SMITH (NULL)
7566 JONES (NULL)
7698 BLAKE (NULL)
7782 CLARK (NULL)
7788 SCOTT (NULL)
7839 KING (NULL)
7876 ADAMS (NULL)
7900 JAMES (NULL)
7902 FORD (NULL)
7934 MILLER (NULL)
7844 TURNER 0.00
7499 ALLEN 300.00
7521 WARD 500.00
7654 MARTIN 1400.00
如果要想在升序排序中将有 Null 值的记录排在后面,可以将 Null 值转为一个最大值(比 comm 中的最大值还要大就行),或者增加一个排序列 is_null,记录有有 Null 值的时候 is_null = 1,其它时候为 0 。
SELECT
empno,
ename,
comm
FROM
emp
ORDER BY IF(comm IS NULL, 1, 0),
comm
重新排序后的结果如下:
empno ename comm
------ ------ ---------
7844 TURNER 0.00
7499 ALLEN 300.00
7521 WARD 500.00
7654 MARTIN 1400.00
7369 SMITH (NULL)
7566 JONES (NULL)
7698 BLAKE (NULL)
7782 CLARK (NULL)
7788 SCOTT (NULL)
7839 KING (NULL)
7876 ADAMS (NULL)
7900 JAMES (NULL)
7902 FORD (NULL)
7934 MILLER (NULL)
4 计算非 Null 值的数量
要统计 emp 表中 comm 字段非 Null 值的数量,可以就这么写:
SELECT
COUNT(comm)
FROM
emp
结果是 4。
count(comm)
-------------
4
注意,如果要统计一张表有多少记录时,不要在允许设置为 Null 值的列上做统计,得出来的结果和实际数据有偏差。注意对比一下使用 count(*)
和 count(comm)
的区别。
count(*)
----------
14
5 聚合 Null 列
聚合函数 sum()
、avg()
、min()
等会忽略 Null 值,在使用 avg()
时要警惕 Null 值。通常的做法是先将列中的 Null 值转为 0,再做聚合操作。
比如,要求员工的平均提成,正确的 SQL 应该这么写:
SELECT
AVG(COALESCE(comm, 0)) AS avg_comm
FROM
emp
聚合的结果:
avg_comm
------------
157.142857
如果直接使用 AVG(comm)
,得出来的结果就千差万别了。
avg(comm)
------------
550.000000
- ASP.NET AJAX(5)__JavaScript原生类型以及Microsoft AJAX Library什么是Microsoft AJAX LibraryObject原生类型Object.pro
- 使用 Octave 来学习 Machine Learning(一)
- ASP.NET AJAX(4)__客户端访问WebService服务器端释放WebService方法客户端访问WebService客户端访问PageMethod错误处理复杂数据类型使用基础客户端代理的
- 讲真,你该做备份的有效性校验了
- memcache安装方法
- 设计模式专题(五)——工厂方法模式
- ASP.NET AJAX(11)__ScriptManagerUpdatePanel的支持成员功能控制成员脚本控件支持成员ScriptMode和ScriptPathLoadScriptsBeforeU
- SQL Server 2016新特性:动态数据屏蔽(DDM)
- ASP.NET AJAX(12)__浏览器兼容功能判断浏览器的类型和版本Sys.Browser针对DOM元素的兼容操作针对DOM事件的兼容操作
- 设计模式专题(六)——原型模式
- ASP.NET AJAX(13)__利用Microsoft AJAX Library开发客户端组件Sys.Component成员Sys.IDisposable成员Sys.INotifyDisposin
- 设计模式专题(七)——建造者模式
- ASP.NET AJAX(14)__UpdatePanel与服务器端脚本控件脚本控件的作用脚本控件的指责Extender模型脚本控件和Extender模型在PostBack中保持状态在UpdatePa
- ASP.NET AJAX(15)__构建高性能ASP.NET AJAX应用UpdatePanel的性能问题使用UpdatePanel的注意事项脚本加载避免脚本阻塞页面显示AjaxControlTool
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【go】剑指offer:不同程序员遇到相同的题
- Spring全家桶之SpringSecurity
- Go实现字符串全排列字典序排列详解
- Go实现字符串全排列详解递归
- springboot整合RSA进行sign签名校验
- Go寻找最长回文字符串——中心扩展法
- Spring高级技术应用——百战商城实现(上)
- 基于Springboot+jpa+thymeleaf+rabbit+SpringBoot mail 的简单项目
- 【go】剑指offer: 删除链表结点O(1)时间复杂度
- Go快速查找有序二维数组的数字
- Go寻找数组中最小的k个数——全部排序和部分排序
- Spring高级技术应用——百战商城实现(下)
- Go 字符串反转问题解决思路
- 剑指offer:go实现从尾到头打印链表
- 【go】剑指offer:3种方法寻找二进制1的个数