大数据管理与分析(第三篇)
SQL 是结构化查询语言,SQL-92 是目前最通用的版本,后续版本引入了更强的功能(如对象关系特性、XML 支持等)
1.Data Definition Language 数据定义语言(DDL)
数据库中的关系集合必须通过 DDL 定义。除了关系集合本身,还可以指定:
每个关系的模式(schema);每个属性的值域(domain);完整性约束(integrity constraints);每个关系维护的索引集合;安全性与访问控制;每个关系在磁盘上的物理存储结构
DDL 用来定义数据库结构,而不是查询或操作数据。
SQL 中的 CREATE、ALTER、DROP 等命令都属于 DDL。
2.SQL中的域类型
char(n):固定长度字符;varchar(n):可变长度字符(最大长度 n);int:整数(取决于机器);smallint:小整数(范围更小);numeric(p,d):定点数,p 是总位数,d 是小数位数;real:单精度浮点数;float(n):浮点数,精度至少 n 位
这些数据类型在不同数据库中的表现可能有差异,例如 Oracle、MySQL、PostgreSQL 对浮点数精度的实现不同。
3.建表语句
SQL 用 CREATE TABLE 定义关系:
create table r (A1 D1,A2 D2, ..., An Dn,
(integrity-constraint1),
...,
(integrity-constraintk))
r 是关系名
Ai 是属性名
完整性约束可以写在列定义后或单独定义
eg:
create table people (
name char(15) not null,
city char(30),
assets int
)
not null 表示该字段不能为空。
4.完整性约束
SQL 支持多种完整性约束,例如:
primary key (A1, …, An) 主键
not null 不允许空值
eg:
create table people (
name char(15),
city char(30),
assets int,
primary key (name))
主键约束会隐含 not null,不需要单独声明。
5.删除表:drop table r
6.增加新属性:alter table r add A D
新属性的值默认为 null。
7.删除属性:alter table r drop A
很多数据库不支持删除列
MySQL、PostgreSQL 等现代数据库都支持 alter table drop column,但一些老系统(例如早期的 Oracle)不支持
8.基本查询结构
SQL 基于集合和关系代数操作,并做了增强。
典型 SQL 查询:
select A1, A2, …, An
from r1, r2, …, rm
where P
Ai:属性
ri:关系(表)
P:谓词(条件)
查询结果仍然是一个关系。
对应关系代数:选择 (σ)、投影 (π)、笛卡尔积 (×)。
9.select 子句:列出查询结果中所需的属性
select 对应关系代数中的投影 (π)。
SQL 名称大小写不敏感。Branch_Name ≡ BRANCH_NAME ≡ branch_name
SQL 允许查询结果中出现重复行。如果想去重,需要在 select 后加 distinct。
select distinct branch_name
from loan
保留重复:
select all branch_name
from loan
关系代数与 SQL 区别:在形式化的关系代数中,结果是集合,天然去重。SQL 默认允许重复,优化性能
形式化关系模型:关系是集合,不能有重复元组。
实际数据库系统:去重代价高 → SQL 默认允许重复
可以用 distinct 强制去重。
SQL 更像是“多重集(multiset)模型”
| ID | name | dept_name | salary |
|---|---|---|---|
| 100 | Kart | CS | 65000 |
| 101 | Crick | History | 90000 |
| 102 | Kim | Finance | 60000 |
| 103 | Wu | Physics | 72000 |
| 104 | John | CS | 80000 |
查询:
select distinct dept_name
from Instructor;
提取所有不同的系名。
结果:
| dept_name |
|---|
| CS |
| History |
| Finance |
| Physics |
重复的“CS” 被去掉了。
查询:
select all dept_name
from Instructor
结果:
| dept_name |
|---|
| CS |
| History |
| Finance |
| Physics |
| CS |
使用 all → 重复行不会被去掉
select * 的用法:
* 表示所有属性。
表 loan:
| loan_number | branch_name | amount |
|---|---|---|
| 0001 | Perryridge | 1000 |
| 0002 | Downtown | 500 |
select *
from loan
结果: 与 loan 表内容相同。
select 中可以出现算术表达式:可使用 +, -, *, / 运算符。运算对象:常数或列属性。
eg:
select number, name, asset*100
from account;
→ 把 asset 字段放大 100 倍。
10.where 子句:指定查询结果必须满足的条件
where 用来写条件 → 对应关系代数中的选择 (σ)
比较结果可以用逻辑运算符组合:and, or, not。比较对象可以是算术表达式的结果。
支持范围:between a and b,区间是闭区间
不等于:<>
eg:
select asset
from account
where name = 'peter' and number > 1200
11.from 子句与连接:列出查询涉及的关系(表)
from 指定涉及的表,对应笛卡尔积.
eg:
select *
from borrower, loan
= borrower × loan
通常结合 where → 做“过滤”,得到连接。
eg:
SELECT ACC.acc_id, CUST.name
FROM CUST, ACC
WHERE CUST.cust_id = ACC.cust_id
→ 查询账户 id 与其所有者姓名。
当多个表中列名无歧义时,可以简化书写;可用别名(AS)。
select customer_name, borrower.loan_number as loan_id, amount
from borrower, loan
where borrower.loan_number = loan.loan_number
SELECT customer_id AS cid
FROM CUST
12.Rename 与元组变量
元组变量通过 FROM 子句的 AS 引入。
AS 可以给列或表重命名
表别名常用于:简化查询; 同一表多次引用(如自连接)。
select C.name, T.loan_number, S.amount
from borrower as T, loan as S
where T.loan_number = S.loan_number;
13.字符串操作
like 用于模式匹配:% 匹配任意长度字符串; _ 匹配任意一个字符
'Intro%' → 匹配以 Intro 开头的字符串
'%Comm%' → 匹配包含“Comm”的字符串(如 “Intro to COMM School”, “Communication”)
'___' → 匹配恰好三个字符的字符串
'___%' → 匹配至少三个字符的字符串
where name like '%lucy%'
→ 匹配含有“lucy”的名字。
可以指定 escape 转义特殊字符。
匹配所有以 “100%” 开头的字符串:
like '100\%%' escape '\'
转义符 escape 表示其后字符当作普通字符。
14.排序
order by 指定排序,默认升序 (asc)。
可写 desc 表示降序。
select distinct customer_name
from borrower, loan
where borrower.loan_number = loan.loan_number
and branch_name = 'Perryridge'
order by customer_name;
order by customer_name desc
SQL 查询结果默认无序,除非显式 order by
15.重复
SQL 允许关系和查询结果中出现重复元组。
多重集 (multiset):允许重复元素的集合。
假设有多重集关系:
r1:
| A | B |
|---|---|
| 1 | a |
| 2 | a |
r2:
| C |
|---|
| 2 |
| 3 |
| 3 |
SELECT B, C
FROM r1, r2
结果:
| B | C |
|---|---|
| a | 2 |
| a | 3 |
| a | 3 |
| a | 2 |
| a | 3 |
| a | 3 |
因为 r2 中有重复的 “3”,结果里也会出现重复。
16.集合运算
SQL 的集合操作:union、intersect、except
对应关系代数中的并集 (∪)、交集 (∩)、差集 (−)。
这些操作默认 自动去重。
如果要保留重复,用多重集版本:
union all
intersect all
except all
SQL 既支持集合语义(去重),也支持多重集语义(允许重复)。
集合操作要求两个查询返回 相同数量和类型的列
(SELECT cust_id FROM CUST)
INTERSECT
(SELECT cust_id FROM ACC)
(SELECT cust_id
FROM CUST)
UNION
(SELECT cust_id
FROM ACC)
(SELECT cust_id
FROM CUST)
EXCEPT
(SELECT cust_id
FROM ACC)
返回 在 CUST 中但不在 ACC 中 的 id。
如果没有这样的 id,结果就是 空集
17.聚合函数
聚合函数:以一个集合的值作为输入,返回一个单一值。
常见函数:
avg 平均值
min 最小值
max 最大值
sum 求和
count 计数
聚合函数 不能直接 用在 where 子句中
SELECT SUM(amount)
FROM DEPOSIT
WHERE acc_id = 'A1'
SELECT COUNT(*)
FROM DEPOSIT
WHERE acc_id = 'A1'
SELECT COUNT(DISTINCT cust_id)
FROM DEPOSIT
WHERE acc_id = 'A1'
DISTINCT 可以避免同一个顾客多次存款被重复计数。
group by 按组聚合
SELECT acc_id, SUM(amount)
FROM DEPOSIT
GROUP BY acc_id
SELECT acc_id, cust_id, SUM(amount)
FROM DEPOSIT
GROUP BY acc_id, cust_id
在 GROUP BY 查询中:SELECT 子句可以包含:
-
分组属性(必须出现在 GROUP BY 中)
-
聚合函数(参数可以是任何属性)
每一组只有一个聚合值。
18.Having 子句
HAVING 只能和 GROUP BY 一起使用,用于对组结果进一步过滤。
找出每个账户的总存款,要求该账户至少有两次存款:
select acc_id, sum(amount)
from deposit
group by acc_id
having count(*) >= 2
执行顺序:
WHERE 在分组前过滤元组。
GROUP BY 把剩余元组分组。
HAVING 在分组后过滤组。
HAVING 子句通常包含聚合函数。
WHERE 子句不能包含聚合函数.
| 特性 | WHERE 子句 | HAVING 子句 |
|---|---|---|
| 执行时机 | 在分组前执行 | 在分组后执行 |
| 操作对象 | 原始数据行(元组) | 分组后的组 |
| 可使用 | 普通列、比较运算符 | 聚合函数、分组后的列 |
| 用途 | 过滤掉不需要的行 | 过滤掉不需要的组 |
19.Null 值
在 SQL 中,元组的某些属性可能取值为 null。
null 表示:未知的值或者值不存在
检查空值:使用 is null 或 is not null
select loan_number
from loan
where amount is null
任意算术表达式中包含 null,结果也是 null。
5 + null → null
任何与 null 的比较,结果都是 unknown。
5 < null → unknown
null <> null → unknown
null = null → unknown
SQL 逻辑是 三值逻辑:true / false / unknown
逻辑运算规则:
OR:
(unknown OR true) = true
(unknown OR false) = unknown
(unknown OR unknown) = unknown
AND:
(true AND unknown) = unknown
(false AND unknown) = false
(unknown AND unknown) = unknown
NOT:
(NOT unknown) = unknown
OR 真值表
| OR | TRUE | FALSE | UNKNOWN |
|---|---|---|---|
| TRUE | TRUE | TRUE | TRUE |
| FALSE | TRUE | FALSE | UNKNOWN |
| UNKNOWN | TRUE | UNKNOWN | UNKNOWN |
AND 真值表
| AND | TRUE | FALSE | UNKNOWN |
|---|---|---|---|
| TRUE | TRUE | FALSE | UNKNOWN |
| FALSE | FALSE | FALSE | FALSE |
| UNKNOWN | UNKNOWN | FALSE | UNKNOWN |
NOT 真值表
| 输入 | NOT 结果 |
|---|---|
| TRUE | FALSE |
| FALSE | TRUE |
| UNKNOWN | UNKNOWN |
还可以用:is unknown/ is not unknown
在 where 子句中,unknown 被当作 false 处理。
除了 count(*),所有聚合函数都会忽略属性值为 null 的元组。
select sum(amount)
from loan
在求和时,null 金额会被忽略。如果所有值都是 null → 结果为 null。
更多推荐


所有评论(0)