0
0
0
第4章(下):SELECT查询全攻略——从单表到嵌套
文章摘要
|
第 4 章(下):SELECT 查询全攻略——从单表到嵌套
查询是 SQL 的核心中的核心。本篇把 SELECT 从最简单的单表查询一路讲到嵌套查询,每个层次配标准例题。学完后,考试的综合 SQL 题基本都能覆盖。
一、SELECT 的完整语法骨架
SELECT [DISTINCT] 目标列
FROM 表 [JOIN 表2 ON 连接条件]
WHERE 行筛选条件
GROUP BY 分组列
HAVING 组筛选条件
ORDER BY 排序列 [ASC|DESC];
执行顺序(理解后能避免一半错误):FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。
二、第一层:单表无条件查询
SELECT * FROM Student; -- 全部列
SELECT Sname, Sage FROM Student; -- 指定列
SELECT Sname AS 姓名, 2026-Sage AS 出生年份 FROM Student; -- 别名与计算列
SELECT DISTINCT Sdept FROM Student; -- 去重
三、第二层:条件查询(WHERE)
常用条件运算:= <> > >= < <=、AND OR NOT、BETWEEN ... AND、IN (...)、LIKE、IS NULL。
SELECT Sname FROM Student
WHERE Sdept='计算机' AND Sage<=20;
SELECT Sno, Grade FROM SC
WHERE Cno='C01' AND Grade BETWEEN 80 AND 90;
SELECT Sno, Cno FROM SC WHERE Grade IS NULL; -- 空值判断必须用 IS NULL
模糊匹配 LIKE:
%:任意长度字符;_:任意单个字符。
SELECT Sname FROM Student WHERE Sname LIKE '张%'; -- 张姓学生
SELECT Sname FROM Student WHERE Sname LIKE '__华'; -- 第三个字是华
四、第三层:排序与聚合
SELECT Sno, Grade FROM SC
WHERE Cno='C01'
ORDER BY Grade DESC; -- 降序;ASC 升序(默认)
聚合函数(对一列计算统计值,忽略 NULL):
| 函数 | 含义 |
|---|---|
| COUNT(*) / COUNT(列) | 行数 / 该列非空个数 |
| SUM(列) / AVG(列) | 求和 / 平均 |
| MAX(列) / MIN(列) | 最大 / 最小 |
五、第四层:分组统计(GROUP BY + HAVING)
-- 每门课的选课人数与平均分
SELECT Cno, COUNT(Sno) AS 人数, AVG(Grade) AS 平均分
FROM SC
GROUP BY Cno;
-- 只看选课人数超过 30 的课程
SELECT Cno, COUNT(Sno) AS 人数
FROM SC
GROUP BY Cno
HAVING COUNT(Sno) > 30;
WHERE 与 HAVING 的区别(必考):WHERE 在分组前筛选行(不能用聚合函数);HAVING 在分组后筛选组(可用聚合函数)。
易错点:SELECT 后面出现的列,要么在 GROUP BY 里,要么在聚合函数里,否则报错。
六、第五层:多表连接查询
-- 两表:学生及其选课成绩
SELECT Student.Sno, Sname, Cno, Grade
FROM Student JOIN SC ON Student.Sno = SC.Sno;
-- 三表:学生姓名、课程名、成绩
SELECT Sname, Cname, Grade
FROM Student
JOIN SC ON Student.Sno = SC.Sno
JOIN Course ON SC.Cno = Course.Cno;
连接条件 = 主码 = 外码。忘记写 ON 连接条件会产生笛卡尔积(行数 = 两表之积),是新手第一大坑。
七、第六层:嵌套(子)查询
子查询 = 查询里再套查询,由内向外执行。
IN 形式(子查询结果是一列值):
-- 选修了'C01'课程的学生姓名
SELECT Sname FROM Student
WHERE Sno IN (SELECT Sno FROM SC WHERE Cno='C01');
比较形式(子查询结果单值):
-- 比全体学生平均年龄小的学生
SELECT Sname FROM Student
WHERE Sage < (SELECT AVG(Sage) FROM Student);
EXISTS 形式(存在量词,内层有结果则外层行保留):
-- 选修了C01的学生
SELECT Sname FROM Student S
WHERE EXISTS (SELECT * FROM SC WHERE SC.Sno=S.Sno AND Cno='C01');
八、综合练习(自测)
给定本文的 Student / Course / SC 三表,写出:
- 计算机系女生名单(按年龄升序);
- 各系的系名与人数(人数 ≥ 2 才显示);
- "数据库"这门课的最高分与平均分;
- 选课总门数超过 3 门的学生的姓名与门数;
- 没有选修'C02'课程的学生学号(提示:NOT IN)。
下一篇:第 5 章——数据更新、视图与索引。
