跳转至

SQL 与关系代数

1. SQL 聚合与执行顺序

统计每个客户在指定月份的交易总额,并筛选总额超过 10,000 元的客户:

1
2
3
4
5
6
SELECT customer_id, SUM(amount) AS total_amount
FROM transactions
WHERE create_time >= '2026-10-01'
  AND create_time < '2026-11-01'
GROUP BY customer_id
HAVING SUM(amount) > 10000;

逻辑执行顺序可理解为:WHERE 先筛行,GROUP BY 分组,聚合函数计算,HAVING 再筛组。WHERE 不能直接筛聚合结果,聚合条件应放在 HAVING。

COUNT(*) 统计行数,COUNT(phone) 不统计 phone 为 NULL 的行。INNER JOIN 只保留匹配记录;LEFT JOIN 保留左表全部记录,右表无匹配时字段为 NULL。

2. 连接与关系代数

关系代数中,SELECT 对应投影 π,WHERE 对应选择 σ,JOIN 对应连接,CROSS JOIN 对应笛卡尔积。连接是从两个关系的笛卡尔积中选取满足条件的元组。

  • θ 连接:满足任意比较条件的连接。
  • 等值连接:连接条件为 =,连接列不要求同名,结果保留两表全部列,因此连接列可能出现两次。
  • 自然连接:在所有同名列上自动做等值连接,并去掉重复连接列。
维度 等值连接 自然连接
条件 显式指定任意列相等 所有同名列自动相等
列名 不要求同名 要求同名
结果列 连接列可能出现两次 重复连接列只保留一次
SQL JOIN ... ON c.id = a.id NATURAL JOIN
1
2
3
4
5
SELECT * FROM customer c
JOIN account a ON c.customer_id = a.customer_id;

SELECT * FROM customer
NATURAL JOIN account;

自然连接属于内连接,无匹配行会被丢弃;需要保留无匹配行时使用外连接。若两表存在多个同名列,自然连接会把它们全部纳入条件,生产 SQL 通常更适合显式 ON。CROSS JOIN 无连接条件,行数等于两表行数相乘,业务上需谨慎。

3. 视图与索引

视图可封装复杂 JOIN 和聚合,也可只暴露必要的列和行,例如柜员视图只展示账号、户名、余额。视图的定义如下:

1
2
3
CREATE VIEW v_teller_account AS
SELECT account_id, customer_name, balance
FROM account;

索引逻辑上是辅助访问对象,物理上会占用磁盘或 SSD,常见结构包括 B+ 树节点、哈希桶和索引页。B+ 树适合精确查找和范围查询;哈希索引适合精确匹配,通常不适合范围查询。联合索引 (customer_id, create_time) 通常可支持按 customer_id 或按两列查询,只按 create_time 查询不一定能充分利用,具体由优化器和实现决定,待核验。

索引不是越多越好:插入和更新需要维护索引,索引字段上做函数处理也可能使索引难以使用:

1
2
3
4
5
6
-- 可能导致索引难以使用
WHERE YEAR(create_time) = 2026

-- 通常更适合范围索引
WHERE create_time >= '2026-01-01'
  AND create_time < '2027-01-01'

索引既是逻辑对象也是物理存储结构,底层存储或索引结构变化时,应用通常仍使用同一 SQL,这体现了物理数据独立性。