关系模型 & SQL 基础
第 2 篇

第一章:数据库系统概论与数据模型 (Introduction & Data Models)#

1. 核心概念解释#

  • 数据库 (Database) vs. 数据库管理系统 (DBMS)
    • 数据库是模拟现实世界的互相关联的数据集合(如:学生名单、音乐专辑列表)。
    • DBMS 是管理这些数据的软件系统,负责数据的存储、查询、安全与一致性。
  • 为什么不用 CSV 文件管理数据?
    • 虽然可以使用文本文件(如 CSV)存储数据,但手动编写代码去解析文件存在巨大缺陷:查询效率低(线性扫描)、难以保证数据一致性(如两个线程同时写入)、缺乏类型安全、原子性无法保证(写到一半断电会导致数据损坏)。
  • 数据模型 (Data Model)
    • 是描述数据的高层抽象,定义了允许存在的数据类型及其相互关系(类似于建筑蓝图的规则)。
    • 关系模型 (Relational Model):当前最主流的数据模型,由 Ted Codd 在 1970 年代提出。它将数据定义为关系 (Relations) 的集合。

2. 关键结论 / 方法#

  • 早期导航式模型的失败
    • 在关系模型之前(如 CODASYL),程序员必须了解数据的物理存储结构(如链表、树),编写复杂的遍历代码(导航)。如果数据库物理结构改变,所有查询代码都要重写。
  • 关系模型的胜利
    • 提供了数据独立性 (Data Independence)
    • 物理数据独立性:用户只需关注逻辑层(Logical Schema),无需关心物理层(Physical Schema)如何存储数据(如文件布局、索引结构)。系统可以在不破坏应用程序的情况下优化物理存储。

3. 易混点或易错点提示#

  • 误区:认为数据库就是 SQL。
    • 纠正:SQL 是语言,DBMS 是系统。市面上有多种 DBMS(Postgres, MySQL, Oracle 等),它们大多遵循关系模型,但实现细节不同。
  • 误区:NoSQL 完全取代了 SQL。
    • 纠正:虽然 NoSQL(如 Mongo, Redis)曾流行,但关系模型仍是基石。现代 SQL 标准已吸收了 JSON、Graph 等特性。

4. 简短复习小结#

DBMS 解决了直接使用文件存储数据带来的完整性与并发问题。关系模型通过将逻辑与物理分离,使程序员能够声明“想要什么数据”而不是“如何找到数据”,这是数据库技术发展的关键转折点。


第二章:关系模型与关系代数 (Relational Model & Algebra)#

1. 核心概念解释#

  • 关系 (Relation)
    • 即数学上的“集合”,在数据库中通常表现为表 (Table)
    • 元组 (Tuple)(即行)和属性 (Attribute)(即列)组成。
    • 无序性:在关系模型理论中,关系是无序集合 (Unordered Set),没有重复元素。
  • 键 (Keys)
    • 主键 (Primary Key):唯一标识元组的属性。
    • 外键 (Foreign Key):指向其他关系中主键的属性,用于建立表与表之间的逻辑联系,而非物理指针。
  • 关系代数 (Relational Algebra)
    • 一种过程化语言 (Procedural Language),定义了查询的执行步骤。它是 SQL 的理论基础,也是数据库引擎内部执行查询的基石。

2. 关键结论 / 公式 / 方法#

  • 七个基本操作符
    1. 选择 (Select, σ\sigma):根据谓词过滤行(对应 SQL 的 WHERE)。
    2. 投影 (Projection, π\pi):选择特定的列,并可能重新排序或计算(对应 SQL 的 SELECT 列表)。
    3. 并集 (Union, \cup):合并两个关系(需结构相同)。
    4. 交集 (Intersection, \cap):取两个关系的共有部分。
    5. 差集 (Difference, -):取存在于第一个关系但不在第二个关系的部分。
    6. 笛卡尔积 (Product, ×\times):将两个关系的行两两组合。
    7. 连接 (Join, \bowtie):结合笛卡尔积与选择操作,基于相关属性合并两个关系。

3. 易混点或易错点提示#

  • Set vs. Bag
    • 易错点:严格的关系代数基于集合 (Set)(无重复),但实际的 SQL 语言基于多重集 (Bag)(允许重复)。SQL 需要显式使用 DISTINCT 去除重复,因为自动去重代价昂贵。
  • 操作顺序
    • 在关系代数中,操作顺序很重要(例如先过滤再 Join 通常比先 Join 再过滤更高效)。SQL 允许用户不关心顺序,由优化器决定。

4. 简短复习小结#

关系模型用表来组织数据,用外键建立联系。关系代数提供了一套操作符(如选择、投影、连接)来处理这些表。理解关系代数有助于理解 SQL 查询在底层是如何被“组装”和执行的。


第三章:SQL 基础与聚合查询 (SQL Basics & Aggregations)#

1. 核心概念解释#

  • SQL (Structured Query Language)
    • 一种声明式语言 (Declarative Language)。用户告诉系统“即使要什么结果”(What),由系统决定“如何计算”(How)。
    • 包含 DML(数据操作)、DDL(数据定义)、DCL(数据控制)。
  • 聚合函数 (Aggregates)
    • 将多行数据压缩为单一值的函数,如 AVG, MIN, MAX, SUM, COUNT

2. 关键结论 / 公式 / 方法#

  • 基本查询结构SELECT -> FROM -> WHERE
  • 分组聚合 (Group By)
    • 利用 GROUP BY 将数据分桶,然后对每个桶进行聚合计算。
  • 过滤聚合结果 (Having)
    • WHERE 用于在聚合前过滤原始行。
    • HAVING 用于在聚合后过滤结果(例如:找出平均分大于 3.9 的课程)。

3. 易混点或易错点提示#

  • GROUP BY 的列限制
    • 如果在 SELECT 中使用了聚合函数(如 AVG(GPA)),那么 SELECT 列表中出现的其他非聚合列(如 CourseID必须出现在 GROUP BY 子句中。否则结果是未定义的(虽然 MySQL 早期版本允许,但这是错误的)。
  • NULL 的处理
    • 聚合函数通常会忽略 NULL 值,但 COUNT(*) 会计算所有行,包括含 NULL 的行。

4. 简短复习小结#

SQL 是通过声明式语法操作关系数据的标准。掌握 GROUP BYHAVING 的区别是进行复杂数据分析的基础。记住:SQL 是基于 Bag(允许重复)的,而关系理论是基于 Set 的。


第四章:高级 SQL 与现实世界的坑 (Advanced SQL & Real-World Implementation)#

1. 核心概念解释#

  • 字符串操作:不同数据库对字符串的大小写敏感度处理不同(Postgres 敏感,MySQL 通常不敏感)。
  • 日期与时间:这是 SQL 中最混乱的部分。不同系统获取当前时间的函数不同(NOW(), CURRENT_TIMESTAMP, GETDATE() 等),计算日期间隔的语法也大相径庭。
  • 嵌套查询 (Nested Queries):在查询中嵌入另一个查询。
  • CTE (Common Table Expressions):使用 WITH 语句创建临时结果集,比嵌套查询更具可读性。

2. 关键结论 / 公式 / 方法#

  • 窗口函数 (Window Functions)
    • 允许在不聚合(不减少行数)的情况下进行“滑动窗口”计算(如移动平均、排名)。
    • 语法:FUNC() OVER (PARTITION BY ... ORDER BY ...)
    • ROW_NUMBER() vs RANK():用于生成行号或排名。
  • Lateral Joins
    • 允许在同一层级中,后续的子查询引用前面表的列(类似于 for loop 内部引用外部变量),非常强大但并非所有系统支持。

3. 易混点或易错点提示#

  • 标准与实现的差异
    • 没有任何一个数据库完全严格遵循 SQL-92 或更新的标准。
    • 例如:Postgres 的双引号 " 用于标识符(表名/列名),单引号 ' 用于字符串常量;而 MySQL 可能混用。
    • 重要提示:在很多系统中,计算两个日期的差值(如 2025-01-01 减去 2024-01-01)可能会导致意想不到的结果(有的返回天数,有的返回莫名其妙的整数),务必查阅具体文档。

4. 简短复习小结#

虽然 SQL 是标准,但不同厂商(Postgres, MySQL, SQLite, DuckDB)在细节上有诸多差异,特别是日期处理和字符串操作。在处理复杂逻辑时,推荐使用 CTE 替代深层嵌套子查询以提高代码可读性。


附录:现代数据栈案例 (dbt)#

  • dbt (data build tool)
    • 背景:传统数据仓库中存在大量混乱的脚本、缺乏版本控制、逻辑重复。
    • 核心思想:将数据转换逻辑(Transform)视为代码。使用 SQL 编写转换逻辑(SELECT 语句),dbt 负责将其物化为表或视图。
    • 价值:带来了软件工程的最佳实践(版本控制、测试、文档、血缘分析)到数据分析领域。

寄语

“SQL 也许不是最完美的语言,但它是在数据领域生存的必备技能。学会它,并理解不同系统间的细微差别,你将受益终身。”