LabHub
学习 学习路径 课程

SQL 实战

用连接把散开的数据接上

在 LabHub 中继续学习

目标

根据场景选择内连接、左外连接、反连接和自连接,并解释 ON 与 WHERE 的区别。

为什么重要

连接时真正需要决定的是:是否保留没有匹配项的行。 若不明确,报表数字会悄悄出错。

左外连接后的 WHERE 尤其危险。对右表列设条件时,未匹配而填充 NULL 的行会因结果为未知而消失,外连接便悄悄变成内连接。另一个问题是扇出:一张订单有三条明细,连接结果就是三行,在其上汇总订单金额会得到三倍。必须始终意识到连接会改变行数。

步骤

  1. 连接订单与客户,把 order_idcustomer_nametotal_amount 保存到视图 v_order_customer
  2. 创建视图 v_customer_orders,保存所有客户及其订单数。列为 idnameorder_count;没有订单的客户为 0,总数仍为 400。
  3. 把从未下单客户的 idname 保存到视图 v_never_ordered
  4. 连接订单明细与商品,把 order_idproduct_namequantityunit_price 保存到视图 v_item_detail
  5. 针对 countryKR 的客户中 statuspaid 的订单,创建明细视图 v_kr_paid_items。列必须以 order_idproduct_id 开头。
  6. 创建视图 v_left_paid,保存所有客户及其已支付订单数。列为 idpaid_count,客户仍为 400。
  7. 针对同城且 tiervip 的客户对,创建视图 v_vip_pairs。列为 a_idb_idcity,同一对不能重复。
  8. 针对 statuspaidshippeddelivered 之一、但没有完成付款的订单,创建视图 v_unpaid_orders

参考

为订单添加客户名称

连接订单与客户,把 order_idcustomer_nametotal_amount 保存到视图 v_order_customer

在 ON 子句中写入连接两个表的列。遗漏连接条件会使行数按笛卡尔积增长。

保留没有订单的客户

创建视图 v_customer_orders,保存所有客户及其订单数。列为 idnameorder_count没有订单的客户应为 0,客户总数仍须为 400。

使用保留左表所有行的连接。计数时若使用 count(*),没有匹配项的行也会被计为 1。

查找从未下单的客户

把从未下单客户的 idname 保存到视图 v_never_ordered

有多种方法检查不存在。NOT EXISTS 对 NULL 是安全的。

连接三个表

连接订单明细与商品,把 order_idproduct_namequantityunit_price 保存到视图 v_item_detail

可以连续使用多次连接。请检查每个连接是否都包含条件。

对连接结果应用条件

针对 countryKR 的客户中 statuspaid 的订单,创建明细视图 v_kr_paid_items。列必须以 order_idproduct_id 开头。

思考客户表条件与订单表条件各自应放在哪里。

确认 ON 与 WHERE 的区别

创建视图 v_left_paid,保存所有客户及其已支付订单数。列为 idpaid_count,客户总数仍须为 400。

在外连接中把右表条件移到 WHERE,会删除没有匹配项的行。请统计客户总数是否保持不变。

将表与自身连接

针对同城且 tiervip 的客户对,创建视图 v_vip_pairs。列为 a_idb_idcity,同一对不能重复出现。

给同一个表使用不同别名。要避免同一对出现两次,可在两个 id 之间使用不等关系条件。

查找未确认付款的订单

针对 statuspaidshippeddelivered 之一、但没有完成付款的订单,创建视图 v_unpaid_orders

必须同时包含完全没有付款行和存在付款行但失败的情况。存在性条件内部也需要包含状态条件。