3. 关系数据库标准语言 SQL
        3.4 数据查询
        
    
        
    
### 数据查询
    SELECT [ALL | DISTINCT] <目标列表达式>, <目标列表达式>, ...
    FROM <表名或视图名> [AS <别名>]
    [WHERE <条件表达式>]
    [GROUP BY <列名1> [HAVING <条件表达式>]]
    [ORDER BY <列名2> [ASC|DESC]];
    
    
### 查询过程
- 根据 WHERE 子句中的条件表达式
- 从 FROM 子句指定的表中选出满足条件的元组
- 根据 SELECT 子句中的目标列表达式
- 选取元组中的属性
- 形成结果表
    
    
### 查询子句
- GROUP BY子句按照指定的列进行分组
- 可在每个组上应用聚集函数
- 若有 HAVING 条件则只输出满足条件的组
- 若有 ORDER BY 子句则对结果表排序
    
    
### 查询指定列
    SELECT Sno, Sname FROM Student;
    
    
### 查询全部列
    SELECT * FROM Student;
    
    
### 查询经过计算的值
    SELECT Sname, 2025 - Sage FROM Student;
    
    
### 指定列别名
    SELECT Sname AS NAME, 2024 - Sage AS BIRTHDAY
    FROM Student;
    
    
### 消除取值重复的行
    SELECT DISTINCT Sno FROM SC;
    
    
### 査询满足条件的元组
- 使用 WHERE 子句
- 比较: <, >, <=, >=, =, !=
- 范围: BETWEEN AND, NOT BETWEEN AND
- 集合: IN, NOT IN
    
    
### 比较
    SELECT Sname
    FROM Student
    WHERE Sdept = 'CS';
    
    
### 范围
    SELECT Sname, Sdept, Sage
    FROM Student
    WHERE Sage BETWEEN 20 AND 23;
    
    
### 集合
    SELECT Sname, Ssex
    FROM Student
    WHERE Sdept IN ('CS', 'MA', 'IS');
    
    
### 字符匹配
- 使用 LIKE 进行字符串匹配
- 可以使用通配符
- "%" 代表任意长度的字符串
- "_" 代表任意单个字符
    
    
### 字符匹配
    SELECT * FROM Student
    WHERE Sno LIKE '201215121';
    SELECT Sname, Sno, Ssex FROM Student
    WHERE Sname LIKE '刘%';
    SELECT Sname FROM Student
    WHERE Sname LIKE '欧阳_';
    SELECT Sname, Sno FROM Student
    WHERE Sname LIKE '_阳%';
    SELECT Sname, Sno, Ssex FROM Student
    WHERE Sname NOT LIKE '刘%';
    
    
### 涉及空值的查询
    SELECT Sno, Cno FROM SC
    WHERE Grade IS NULL;
    SELECT Sno, Cno FROM SC
    WHERE Grade IS NOT NULL;
- 使用 IS NULL 谓词查询空值
- 使用 IS NOT NULL 谓词查询非空值
    
    
### 多重条件查询
    SELECT Sname FROM Student
    WHERE Sdept = 'CS' AND Sage < 20;
    SELECT Sname, Ssex
    FROM Student
    WHERE Sdept = 'CS' OR Sdept = 'MA' OR Sdept = 'IS';
- 使用逻辑运算符 AND 和 OR 连接多个查询条件
- AND 的优先级高于 OR
- 可以使用括号改变优先级
    
    
### ORDER BY子句
    SELECT Sno, Grade FROM SC WHERE Cno = '3'
    ORDER BY Grade DESC;
    SELECT * FROM Student ORDER BY Sdept, Sage DESC;
- 对查询结果按照属性列排序
- 可以对一个或多个属性列排序
- 默认按升序排列
    
    
### 聚集函数
- COUNT 函数
- SUM 函数
- AVG 函数
- MAX 函数
- MIN 函数
    
    
### COUNT 函数
    SELECT COUNT(*) FROM Student;
    SELECT COUNT(DISTINCT Sno) FROM SC;
- 用于统计元组个数或某一列中值的个数
- 查询学生总人数
- 查询选修了课程的学生人数
    
    
### SUM 函数
    SELECT SUM(Grade) FROM SC WHERE Cno = '1';
- 用于计算某一列值的总和 (此列必须是数值型) .
- 计算选修 1 号课程的学生平均成绩
    
    
### AVG 函数
    SELECT AVG(Grade) FROM SC WHERE Cno = '1';
- 用于计算某一列值的平均值 (此列必须是数值型) 
- 计算选修 1 号课程的学生平均成绩
    
    
### MAX 函数
    SELECT MAX(Grade) FROM SC WHERE Cno = '1';
- 用于求一列值中的最大值
- 查询选修 1 号课程的学生最高分数
    
    
### MIN 函数
    SELECT MIN(Grade) FROM SC WHERE Cno = '1';
- 用于求一列值中的最小值
- 查询选修1号课程的学生最低分数
    
    
### 使用聚集函数的注意事项
- 遇到空值时除 `COUNT(*)` 外都只处理非空值
- `WHERE` 子句中不能使用聚集函数作为条件表达式
- 聚集函数只能用于 `SELECT` 子句和 `GROUP BY` 中的 `HAVING` 子句
    
    
### GROUP BY 子句
    SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno;
    SELECT Sno FROM SC
    GROUP BY Sno
    HAVING COUNT(*) > 3;
- 将查询结果按某一列或多列的值分组
- 为了细化聚集函数的作用对象
- 求各个课程号及相应的选课人数
- 查询选修了三门以上课程的学生学号
    
    
### WHERE 与 HAVING 的区别
-  `WHERE` 子句与 `HAVING` 短语的区别在于作用对象不同
-  `WHERE` 子句作用于基本表或视图
-  `HAVING` 短语作用于组
    
    
### 查询示例
    SELECT Sno, AVG(Grade)
    FROM SC
    GROUP BY Sno
    HAVING AVG(Grade) >= 90;
- 平均成绩大于等于 90 分的学生学号和平均成绩
    
    
### 连接查询
- 同时涉及两个以上的表的查询操作
- 等值连接查询
- 自然连接查询
- 非等值连接查询
- 自身连接查询
- 外连接查询
- 复合条件连接查询
    
    
### 等值连接查询
- 用于连接两个表的条件称为连接条件
- <表名1>.<列名1><比较运算符><表名2>.<列名2>
- 比较运算符主要有=, >, <, <=, >=, != (或<>) 等
- 连接条件中的列名称为连接字段
- 当连接运算符为 = 时称为等值连接
    
    
### 连接查询
    SELECT Student.*, SC.*
    FROM Student, SC
    WHERE Student.Sno = SC.Sno;
- 查询学生及其选修课程
    
    
### 自身连接
- 一个表与自身进行连接
    
    
### 查询每门课的间接先修课
    SELECT FIRST.Cno, SECOND.Cpno
    FROM Course FIRST, Course SECOND
    WHERE FIRST.Cpno = SECOND.Cno;
- 为了得到每门课的间接先修课 (即先修课的先修课), 需要将 Course 表与自身进行连接
- 为 Course 表取别名为 FIRST 和 SECOND
    
    
### 嵌套查询
    SELECT Sname
    FROM Student
    WHERE Sno IN
        (SELECT Sno
        FROM SC
        WHERE Cno='2');
- 一个 `SELECT-FROM-WHERE` 语句是一个查询块
- 查询块可以嵌套
    
    
### 嵌套查询
- 上层的査询块称为外层查询或父查询
- 下层查询块称为内层查询或子查询
- SQL 语言允许多层嵌套査询
- 子査询的 `SELECT` 语句不能用 `ORDER BY` 子句
    
    
### 带 IN 的子查询
    SELECT Sno,Sname,Sdept
    FROM Student
    WHERE Sdept IN
        (SELECT Sdept
        FROM Student
        WHERE Sname='刘晨');
- 子查询的结果往往是一个集合
- `IN` 在嵌套査询中最常使用
    
    
### 相关与不相关子查询
- 查询条件是否依赖于父查询
    
    
### 带比较运算符的子查询
    SELECT Sno,Sname,Sdept
    FROM Student
    WHERE Sdept =
        (SELECT Sdept
        FROM Student
        WHERE Sname='刘晨');
- 内层查询返回单个值时
- 可以用比较运算符
    
    
### 带 ANY 或 ALL 的子查询
- 返回多值时要用 ANY 或 ALL 修饰符
- 必须同时使用比较运算符
- > ANY 大于子查询结果中的某个值 MIN
- > ALL 大于子查询结果中的所有值 MAX
- < ANY 小于子査询结果中的某个值 MAX
- < ALL 小于子查询结果中的所有值 MIN
- >= ANY 大于等于子查询结果中的某个值 MIN
- >= ALL 大于等于子査询结果中的所有值 MAX
    
    
- <= ANY 小于等于子査询结果中的某个值 MAX
- <= ALL 小于等于子查询结果中的所有值 MIN
- = ANY 等于子查询结果中的某值 IN
- = ALL 等于子查询结果中的所有值 (无意义)
- != ANY 不等于子査询结果中的某个值 (无意义)
- != ALL 不等于子査询结果中的任何一个值 NOT IN
    
    
### 集合查询
- 査询结果是元组集合
- 多个 `SELECT` 语句的结果可集合操作
- 并操作 `UNION`
- 交操作 `INTERSECT`
- 差操作 `EXCEPT`
- 各查询结果的列数必须相同
- 对应项的数据类型也必须相同
    
    
### 例 64
    SELECT *
    FROM Student
    WHERE Sdept = 'CS'
    UNION
    SELECT *
    FROM Student
    WHERE Sage <= 19;
- `UNION` 合并多个查询结果时会自动去重
    
    
### 例 66
    SELECT *
    FROM Student
    WHERE Sdept = 'CS'
    INTERSECT
    SELECT *
    FROM Student
    WHERE Sage <= 19;
    
    
### 例 68
    SELECT *
    FROM Student
    WHERE Sdept = 'CS'
    EXCEPT
    SELECT *
    FROM Student
    WHERE Sage <= 19;
    
    
### 基于派生表的查询
    SELECT Sno, Cno
    FROM SC, (SELECT Sno, Avg(Grade)
              FROM SC GROUP BY Sno)
              AS Avg_sc(avg_sno,avg_grade)
    WHERE SC.Sno = Avg_sc.avg_sno
        and SC.Grade >= Avg_sc.avg_grade
- 子查询可以出现在 `FROM` 子句中
- 子查询生成临时派生表
    
    
### SELECT 语句
    SELECT [ALL | DISTINCT] <目标列表达式> [别名]
            [, <目标列表达式> [别名] ]...
    FROM <表名或视图名> [别名]
            [, <表名或视图名> [别名] ] ... |
            ( <SELECT语句> ) [AS] <别名>
    [WHERE <条件表达式> ]
    [GROUP BY <列名 1> [HAVING <条件表达式> ] ]
    [ORDER BY <列名 2> [ASC|DESC] ];
    
    
### 目标列表达式的可选格式
- *
- <表名>.*
- COUNT( [DISTINCT | ALL] *)
- [ <表名> .] <属性列名表达式> [, [ <表名> .] <属性列名表达式> ] ...
    
    
### 聚集函数的一般格式
- COUNT
- SUM
- AVG
- MAX
- MIN
- 后接 ( [DISTINCT | ALL] <列名> )
    
    
### WHERE 子句的条件表达式
- 比较运算符θ
- BETWEEN
- IN
- LIKE
- IS NULL
- EXISTS
- 条件表达式 1 [AND | OR] 条件表达式 2
    
    

    
    
### 3.4 数据查询
- 在 SQL 中, 如何使用 SELECT 语句检索数据?
- 如何使用 WHERE 子句过滤 SELECT 语句的结果?
- 如何使用 ORDER BY 子句对查询结果进行排序?
- 在 SQL 中,常见的聚合函数有哪些?
- 如何使用 GROUP BY 子句分组操作?
----
[ 3.3 数据定义](dbpa-3-3.html#/overview)
[| 练习 |](dbpa-exec.html)
[ 3.5 数据更新](dbpa-3-5.html#/overview)