前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CMU 15-445 -- 关系型数据库重点概念回顾 - 01

CMU 15-445 -- 关系型数据库重点概念回顾 - 01

作者头像
大忽悠爱学习
发布2023-10-11 08:50:48
3140
发布2023-10-11 08:50:48
举报
文章被收录于专栏:c++与qt学习
CMU 15-445 -- 关系型数据库重点概念回顾 - 01

引言

本系列为 CMU 15-445 Fall 2022 Database Systems 数据库系统 [卡内基梅隆] 课程重点知识点摘录,附加个人拙见,同样借助CMU 15-445课程内容来完成MIT 6.830 lab内容。

CMU 15-445实验如果有空,后期会在本专栏补充上。


Relational Data Model

DBMS

所有系统都会产生数据,因此数据库几乎是所有系统都不可或缺的模块。在早期,各个项目各自造轮子,因为每个轮子都是为应用量身打造,这些系统的逻辑层(logical)和物理层(physical)普遍耦合度很高。

Ted Codd 发现这个问题后,提出 DBMS 的抽象(Abstraction):

  • 用简单的、统一的数据结构存储数据
  • 通过高级语言操作数据
  • 逻辑层和物理层分离,系统开发者只关心逻辑层,而 DBMS 开发者才关心物理层。

数据模型

在逻辑层中,我们通常需要对所需存储的数据进行建模。如今,市面上有的数据模型包括:

  • Relational => 大部分 DBMS 属于关系型,也是本课讨论的重点
  • Key/Value
  • Graph
  • Document
  • Column-family
  • Array/Matrix

Relational Model

Relation & Tuple

每个 Relation 都是一个无序集合(unordered set),集合中的元素称为 tuple,每个 tuple 由一组属性构成,这些属性在逻辑上通常有内在联系。

Primary Keys

primary key 在一个 Relation 中唯一确定一个 tuple,如果你不指定,有些 DBMSs 会自动帮你生成 primary key。

Foreign Keys

foreign key 唯一确定另一个 relation 中的一个 tuple


Data Manipulation Languages (DML)

在 Relational Model 中从数据库中查询数据通常有两种方式:Procedural 与 NonProcedural:

  • Procedural:查询命令需要指定 DBMS 执行时的具体查询策略,如 Relational Algebra
  • Non-Procedural:查询命令只需要指定想要查询哪些数据,无需关心幕后的故事,如 SQL

使用哪种方式是具体的实现问题,与 Relational Model 本身无关。


Relational Algebra

relational algebra 是基于 set algebra 提出的,从 relation 中查询和修改 tuples 的一些基本操作,它们包括:

在这里插入图片描述
在这里插入图片描述

将这些操作串联起来,我们就能构建更复杂的操作

注意

  • 使用 Relation Algebra 时,我们实际上指定了执行策略,如:
在这里插入图片描述
在这里插入图片描述
  • 它们所做的事情都是 ”返回 R 和 S Join 后的结果中,b_id 等于 102 的 tuples“。

虽然 Relational Algebra 只是 Relational Model 的具体实现方式,但在之后的课程将会看到它对查询优化、执行的帮助。

本部分参考课程链接


Advanced SQL

在 Relational Model 下构建查询语句的方式分为两种:

  • Procedural 和 Non-Procedural。

第一节课中已经介绍了 Relational Algebra,它属于 Procedural 类型,而本节将介绍的 SQL 属于 Non-Procedural 类型。使用 SQL 构建查询时,用户只需要指定它们想要的数据,而不需要关心数据获取的方式,DBMS 负责理解用户的查询语义,选择最优的方式构建查询计划。

SQL 的历史

  • ”SEQUAL" from IBM’s System R prototype
    • Structured English Query Language
    • Adopted by Oracle in the 1970s
  • IBM releases DB2 in 1983
  • ANSI Standard in 1986. ISO in 1987
    • Structured Query Language

当前 SQL 的标准是 SQL 2016,而目前大部分 DBMSs 至少支持 SQL-92 标准,具体的系统对比信息可以到这里查询。


SQL

SQL 基于:

  • Aggregations + Group By
  • String / Date / Time Operations
  • Output Control + Redirection
  • Nested Queries
  • Common Table Expressions
  • Window Functions

本节使用的示例数据库如下所示:

代码语言:javascript
复制
student(sid, name, login, gpa)

sid

name

login

age

gpa

53666

Kanye

kayne@cs

39

4.0

53668

Bieber

jbieber@cs

22

3.9

代码语言:javascript
复制
enrolled(sid, cid, grade)

sid

cid

grade

53666

15-445

C

53688

15-721

A

代码语言:javascript
复制
course(cid, name)

cid

name

15-445

Database Systems

15-721

Advanced Database Systems


Aggregates

Aggregates 通常返回一个值,它们包括:

  • AVG(col)
  • MIN(col)
  • MAX(col)
  • SUM(col)
  • COUNT(col)

举例如下:

  • count.sql
代码语言:javascript
复制
SELECT COUNT(login) AS cnt FROM student WHERE login LIKE '%@cs';
SELECT COUNT(*) AS cnt FROM student WHERE login LIKE '%@cs';
SELECT COUNT(1) AS cnt FROM student WHERE login LIKE '%@cs';
  • multiple.sql
代码语言:javascript
复制
SELECT AVG(gpa), COUNT(sid) FROM student WHERE login LIKE '%@cs';
  • distinct.sql
代码语言:javascript
复制
SELECT COUNT(DISTINCT login) FROM student WHERE login LIKE '%@cs';

aggregate 与其它通常的查询列不可以混用,比如:

  • mix.sql
代码语言:javascript
复制
SELECT AVG(s.gpa), e.cid FROM enrolled AS e, student AS s WHERE e.sid = s.sid;

不同 DBMSs 的输出结果不一样,严格模式下,DBMS 应该抛错。


Group By

group by 就是把记录按某种方式分成多组,对每组记录分别做 aggregates 操作,如求每门课所有学生的 GPA 平均值:

代码语言:javascript
复制
SELECT AVG(s.gpa), e.cid FROM enrolled AS e, student AS s WHERE e.sid = s.sid GROUP BY e.cid;

所有非 aggregates 操作的字段,都必须出现在 group by 语句,如下面示例中的 e.cid 和 s.name:

代码语言:javascript
复制
SELECT AVG(s.gpa), e.cid, s.name FROM enrolled AS e, student AS s WHERE e.sid = s.sid GROUP BY e.cid, s.name;

Having

基于 aggregation 结果的过滤条件不能写在 WHERE 中,而应放在 HAVING 中,如:

代码语言:javascript
复制
SELECT AVG(s.gpa) AS avg_gpa, e.cid FROM enrolled AS e, student AS s WHERE e.sid = s.sid GROUP BY e.cid HAVING avg_gpa > 3.9;

Output Redirection

将查询结果储存到另一张表上:

  • 该表必须是已经存在的表
  • 该表的列数,以及每列的数据类型必须相同

SQL-92.sql:

代码语言:javascript
复制
SELECT DISTINCT cid INTO CourseIds FROM enrolled;

INSERT INTO CourseIds ( SELECT DISTINCT cid FROM enrolled );

MySQL.sql:

代码语言:javascript
复制
CREATE TABLE CourseIds ( SELECT DISTINCT cid FROM enrolled );

Output Control
Order By

语法: ORDER BY <column*> [ASC|DESC]

代码语言:javascript
复制
SELECT sid, grade FROM enrolled WHERE cid = '15-721' ORDER BY grade;

按多个字段分别排序:

代码语言:javascript
复制
SELECT sid FROM enrolled WHERE cid = '15-721' ORDER BY grade DESC, sid ASC;

Limit

语法:LIMIT <count> [offset]

代码语言:javascript
复制
SELECT sid, name FROM student WHERE login LIKE '%@cs' LIMIT 10;

SELECT sid, name FROM student WHERE login LIKE '%@cs' LIMIT 20 OFFSET 10;

Nested Queries

nested queries 包含 inner queries 和 outer queries,前者可以出现在 query 的任何位置,且 inner queries 可以引用 outer queries 中的表信息。

例 1:获取所有参与 ‘15-445’ 这门课所有学生的姓名:

代码语言:javascript
复制
SELECT name FROM student WHERE sid IN ( SELECT sid FROM enrolled WHERE cid = '15-445' );
代码语言:javascript
复制
SELECT (SELECT S.name FROM student AS S WHERE S.sid = E.sid) AS sname FROM enrolled AS E WHERE cid = '15-445';

语法中支持的谓词包括:

  • ALL: 所有 inner queries 返回的记录都必须满足条件
  • ANY:任意 inner queries 返回的记录满足条件即可
  • IN:与 ANY 等价
  • EXISTS: inner queries 返回的表不为空
代码语言:javascript
复制
SELECT name FROM student WHERE sid ANY ( SELECT sid FROM enrolled WHERE cid = '15-445')

例 2:找到至少参与一门课程的所有学生中,id 最大的

代码语言:javascript
复制
SELECT sid, name FROM student WHERE sid >= ALL (SELECT sid FROM enrolled);

SELECT sid, name FROM student WHERE sid IN (SELECT MAX(sid) FROM enrolled);

SELECT sid, name FROM student WHERE sid IN (SELECT sid FROM enrolled ORDER BY sid DESC LIMIT 1);

例 3:找到所有没有学生参与的课程

代码语言:javascript
复制
SELECT * FROM course WHERE NOT EXISTS (SELECT * FROM enrolled WHERE course.cid = enrolled.cid);

nested queries 比较难被优化。


Common Table Expressions

在一些复杂查询中,创建一些中间表能够使得这些查询逻辑更加清晰:

代码语言:javascript
复制
WITH cteName AS (SELECT 1) SELECT * FROM cteName

WITH cteName (col1, col2) AS (SELECT 1, 2) SELECT col1 + col2 FROM cteName

WITH cteName1(col) AS (SELECT 1),cteName2(col) AS (SELECT 2) SELECT C1.col + C2.col FROM cteName1 AS C1, cteName2 AS C2;

例 1:找到所有参与课程的学生中 id 最大的

代码语言:javascript
复制
WITH cteSource(maxId) AS (
    SELECT MAX(sid) FROM enrolled
)
SELECT name FROM student, cteSource
 WHERE student.sid = cteSource.maxId

例 2:打印 1-10

代码语言:javascript
复制
WITH RECURSIVE cteSource (counter) AS (
    (SELECT 1)
    UNION ALL
    (SELECT counter + 1 FROM cteSource
      WHERE counter < 10)
)
SELECT * FROM cteSource;

String Operations

DBMS

String Case

String Quotes

SQL-92

Sensitive

Single Only

Postgres

Sensitive

Single Only

MySQL

InSensitive

Single/Double

SQLite

Sensitive

Single/Double

Oracle

Sensitive

Single Only

如在 condition 中判断两个字符串忽略大小写后是否相等:

代码语言:javascript
复制
/* SQL-92 */
WHERE UPPER(name) = UPPER('KaNyE')

/* MySQL */
WHERE name = "KaNyE"
String Matching
代码语言:javascript
复制
SELECT * FROM enrolled AS e
 WHERE e.cid LIKE '15-%';

SELECT * FROM student AS s
 WHERE s.login LIKE '%@c_';
String Operations

SQL-92 定义了一些 string 函数,如

代码语言:javascript
复制
SELECT SUBSTRING(name, 0, 5) AS abbrv_name
  FROM student WHERE sid = 53688;

SELECT * FROM student AS s
 WHERE UPPER(e.name) LIKE 'KAN%';

不同 DBMS 有不同的 string 函数(没有完全遵从 SQL-92 标准),如连接两个 strings

代码语言:javascript
复制
/* SQL-92 */
SELECT name FROM student
 WHERE login = LOWER(name) || '@cs';

/* MySQL */
SELECT name FROM student
 WHERE login = LOWER(name) + '@cs';
SELECT name FROM student
 WHERE login = CONCAT(LOWER(name), '@cs')
Date/Time Operations

不同的 DBMS 中的定义和用法不一样,具体见各 DBMS 的文档。

Window Functions

主要用于在一组记录中,对每一条记录进行一些计算,如:

例 1:

代码语言:javascript
复制
SELECT *, ROW_NUMBER() OVER () AS row_num FROM enrolled;

会得到类似下表:

在这里插入图片描述
在这里插入图片描述

例 2:

代码语言:javascript
复制
SELECT cid, sid,
       ROW_NUMBER() OVER (PARTITION BY cid)
  FROM enrolled
 ORDER BY cid;

可是得到类似下表:

在这里插入图片描述
在这里插入图片描述

例 3:找到每门课获得最高分的学生

代码语言:javascript
复制
SELECT * FROM (
  SELECT *,
         RANK() OVER (PARTITION BY cid ORDER BY grade ASC) AS rank
    FROM enrolled
  ) AS ranking
WHERE ranking.rank = 1

通俗易懂的学会:SQL窗口函数

本部分参考课程链接

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CMU 15-445 -- 关系型数据库重点概念回顾 - 01
  • 引言
  • Relational Data Model
    • DBMS
      • 数据模型
        • Relational Model
          • Data Manipulation Languages (DML)
            • Relational Algebra
        • Advanced SQL
          • SQL 的历史
            • SQL
              • Aggregates
              • Group By
              • Having
              • Output Redirection
              • Output Control
              • Nested Queries
              • Common Table Expressions
              • String Operations
              • Date/Time Operations
              • Window Functions
          相关产品与服务
          云数据库 MySQL
          腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档