跳转到主要内容
模块 4 · 第 2 课(共 4)课程中的14/57~10 min
模块课程(2/4)

处理 NULL:IS NULL 和 COALESCE

在 employees 数据集中,Andrea Costa 很特别:他有 department_id = NULL。你已经刷过 NULL (与 LEFT JOIN),但现在是认真对待它的时候了:SQL 中的 NULLs 与任何其他值不同,忽略它们是其中之一 生产代码中错误的主要原因。

NULL 不是零,不是空字符串

NULL 表示未知/缺失值。它不是 0,不是 '',不是 false。这是*“我不知道”*。由此得出一个令人惊讶的性质: NULL 不等于任何东西,甚至不等于它本身。

SQL
-- All these expressions return NULL (not true!):
SELECT NULL = NULL;       -- NULL
SELECT NULL = 0;          -- NULL
SELECT NULL <> 'qualcosa'; -- NULL

具体结果:WHERE column = NULL 永远不会起作用。你必须使用 专用运算符 IS NULL / IS NOT NULL:

SQL
-- Employees without a department:
SELECT first_name, last_name
FROM   employees
WHERE  department_id IS NULL;

-- Employees WITH a department:
SELECT first_name, last_name
FROM   employees
WHERE  department_id IS NOT NULL;

COALESCE — NULL 后备

当数据是 缺少:字符串 '(none)'、零、默认日期。该功能 这正是**COALESCE(a, b, c, ...):它返回第一个 列表中的非 NULL 参数**。

SQL
-- Show the department_id, or 0 if missing:
SELECT first_name, last_name, COALESCE(department_id, 0) AS dept
FROM   employees;

与 LEFT JOIN 结合使用,它对于报告来说变得非常强大:

SQL
SELECT e.first_name,
       e.last_name,
       COALESCE(d.name, '(nessun dipartimento)') AS dipartimento
FROM   employees   AS e
LEFT JOIN departments AS d ON e.department_id = d.id;

结果:所有员工返回,并带有部门名称或明确的名称 为那些没有标签的人提供标签。

NULL 和聚合

聚合函数 忽略 NULLs(COUNT(*) 除外):

  • COUNT(department_id) 仅计算具有值的行;
  • AVG(salary) 平均值忽略 NULLs — 它不将它们视为 0;
  • SUM(...) 仅对非 NULL 值求和。

这几乎总是您想要的。但很高兴知道:如果您是 寻找*“员工总数”*使用COUNT(*),而不是 COUNT(department_id)。

尝试一下

锻炼#sql.m4.l2.e1
尝试:0加载中...

对于每个员工,显示名字 (first_name)、姓氏 (last_name) 和“dipartimento_id”列,该列等于其部门 ID,如果未分配,则为 -1。三列,每个员工一行。

正在加载编辑器...
显示提示

使用 COALESCE(department_id, -1) 将 NULL 替换为 -1。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m4.l2.e2
尝试:0加载中...

返回所有员工的名字 (first_name)、姓氏 (last_name) 和部门名称 (departments.name),当部门缺失时显示“(nessuno)”。使用左连接 + 合并。

正在加载编辑器...
显示提示

COALESCE(d.name, '(nessuno)') 处理 LEFT JOIN 引入的 NULL。

3 次尝试后可用的解决方案