【数据库】SQL语言:SELECT语句的练习(例题)

复试面试准备数据库,本文为知识点例题讲解,例题来源课上笔记


1. 定义与基础

1.1基本语法

  • SELECT: 指定要查询的列。
  • FROM: 指定要查询的表。
  • WHERE: 可选,用于过滤记录。

SELECT 语句用于从表中查询数据,其基础格式如下:

复制代码
SELECT 列名 FROM 表名 WHERE 条件 ORDER BY 排序顺序;

2. 基础查询

2.1 查询所有数据

复制代码
SELECT * FROM 学生;

假设 学生 表数据如下:

学号 姓名 专业
1 张三 软件
2 李四 网络
3 王五 软件

2.2 查询指定字段

复制代码
SELECT 学号, 姓名
FROM 学生
WHERE 专业 = '软件';

必修课 表数据如下:

课号 课程名
101 数据库
102 数据结构
101 数据库

列出软件专业全部学生的学号及姓名

学号 姓名
1 张三
3 王五

2.3 去重查询

复制代码
SELECT DISTINCT 课号
FROM 必修课;

列出所有必修课的课号

课号
101
102

3. 筛选数据 (WHERE)

3.1 基础条件查询

复制代码
SELECT * FROM students WHERE age > 18;

3.2 多条件查询

  1. 求 1 号课成绩⼤于 80 分的学⽣的学号及成绩,并按成绩由⾼到低列出。

    SELECT 学号, 成绩
    FROM 选课
    WHERE 课号 = '1' AND 成绩 > 80
    ORDER BY 成绩 DESC;

假设 选课 表数据如下:

学号 课号 成绩
1 1 85
2 1 75
3 1 90
4 2 88
5 1 95

查询结果

执行上述查询后,结果将是:

学号 成绩
5 95
3 90
1 85

2.列出非软件专业学生的名单。

方法一:使用 <> 运算符
复制代码
SELECT 姓名
FROM 学生
WHERE 专业 <> "软件";
方法二:使用 NOT 运算符
复制代码
SELECT 姓名
FROM 学生
WHERE NOT 专业 = "软件";
方法三:使用 != 运算符
复制代码
SELECT 姓名
FROM 学生
WHERE 专业 != "软件";

示例数据

假设 学生 表数据如下:

学号 姓名 专业
1 张三 软件
2 李四 网络
3 王五 软件
4 赵六 电子

查询结果

无论使用哪种方法,查询结果都将是:

姓名
李四
赵六
1. 列出选修1号课或3号课的全体学生的学号和成绩

方法一 :使用 OR 运算符

复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 = "1" OR 课号 = "3";

方法二 :使用 IN 运算符

复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 IN ("1", "3");
2. 列出没有选修1号课和3号课的学生的学号和成绩

方法一 :使用 !=AND 运算符

复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 != "1" AND 课号 != "3";

方法二 :使用 NOT IN 运算符

复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 NOT IN ("1", "3");

示例数据

假设 选课 表数据如下:

学号 课号 成绩
1 1 85
2 2 75
3 1 90
4 3 88
5 2 95

查询结果
1. 列出选修1号课或3号课的全体学生的学号和成绩

无论使用哪种方法,查询结果都将是:

学号 成绩
1 85
3 90
4 88
2. 列出没有选修1号课和3号课的学生的学号和成绩

无论使用哪种方法,查询结果都将是:

学号 成绩
2 75
5 95

3.3 模糊查询

. 列出所有98级学生的学生成绩情况

方法一 :使用 LIKE "98%"

复制代码
SELECT *
FROM 选课
WHERE 学号 LIKE "98%";

方法二 :使用 LIKE "98_"

复制代码
SELECT *
FROM 选课
WHERE 学号 LIKE "98_";
2. 列出非98级学生的学生成绩情况

方法一 :使用 NOT LIKE "98%"

复制代码
SELECT *
FROM 选课
WHERE 学号 NOT LIKE "98%";

方法二 :使用 NOT LIKE "98_"

复制代码
SELECT *
FROM 选课
WHERE 学号 NOT LIKE "98_";

示例数据

假设 选课 表数据如下:

学号 课号 成绩
98001 1 85
98002 1 75
99001 1 90
98003 2 88
99002 2 95

查询结果
1. 列出所有98级学生的学生成绩情况
  • 方法一 ​(LIKE "98%"):

    学号 课号 成绩
    98001 1 85
    98002 1 75
    98003 2 88
  • 方法二 ​(LIKE "98_"):

    学号 课号 成绩
    98001 1 85
    98002 1 75
    98003 2 88
2. 列出非98级学生的学生成绩情况
  • 方法一 ​(NOT LIKE "98%"):

    学号 课号 成绩
    99001 1 90
    99002 2 95
  • 方法二 ​(NOT LIKE "98_"):

    学号 课号 成绩
    99001 1 90
    99002 2 95

3.4 范围查询

1. 查询成绩在70到80分之间的选课记录

方法一 :使用 >=<= 运算符

复制代码
SELECT *
FROM 选课
WHERE 成绩 >= 70 AND 成绩 <= 80;

方法二 :使用 BETWEEN 运算符

复制代码
SELECT *
FROM 选课
WHERE 成绩 BETWEEN 70 AND 80;
2. 查询不在70到80分范围内的选课记录

方法一 :使用 <=>= 运算符

复制代码
SELECT *
FROM 选课
WHERE 成绩 <= 70 OR 成绩 >= 80;

方法二 :使用 NOT BETWEEN 运算符

复制代码
SELECT *
FROM 选课
WHERE 成绩 NOT BETWEEN 70 AND 80;

示例数据

假设 选课 表数据如下:

学号 课号 成绩
1 1 65
2 1 75
3 1 85
4 2 70
5 2 80

查询结果
1. 查询成绩在70到80分之间的选课记录

无论使用哪种方法,查询结果都将是:

学号 课号 成绩
2 1 75
4 2 70
5 2 80
2. 查询不在70到80分范围内的选课记录

无论使用哪种方法,查询结果都将是:

学号 课号 成绩
1 1 65
3 1 85

4. 排序数据 (ORDER BY)

4.1 按成绩降序排列

复制代码
SELECT * FROM students ORDER BY score DESC;

4.2 按年龄升序、成绩降序排列

复制代码
SELECT * FROM students ORDER BY age ASC, score DESC;

5. 聚合查询 (GROUP BY + HAVING)

5.1 统计每个年龄段的学生人数

复制代码
SELECT age, COUNT(*) AS student_count FROM students GROUP BY age;

5.2 计算不同性别的平均成绩

复制代码
SELECT gender, AVG(score) AS avg_score FROM students GROUP BY gender;

5.3 统计学生数量大于2的年龄段

复制代码
SELECT age, COUNT(*) AS student_count FROM students GROUP BY age HAVING COUNT(*) > 2;

6. 连接查询 (JOIN) 重要!!

6.​1 连接查询的基本概念

  • 连接查询:用于从多个表中提取数据,并通过相关列建立表之间的关联。
  • 常用连接类型
    • 内连接(INNER JOIN)​:只返回满足连接条件的记录。
    • 外连接(LEFT JOIN, RIGHT JOIN, FULL JOIN)​:返回满足连接条件的记录以及不满足条件的部分记录。
    • 自连接(SELF JOIN)​:将表与自身连接。
  • 连接条件 :通过 ONWHERE 子句指定表之间的关联列。

​6.2 内连接查询

知识点讲解
  • INNER JOIN:默认的连接类型,返回满足连接条件的记录。

  • 语法

    复制代码
    SELECT 列1, 列2, ...
    FROM 表1
    INNER JOIN 表2 ON 表1.列 = 表2.列;
  • 等价写法 :在 WHERE 子句中指定连接条件(旧式写法)。

SQL 代码示例
  1. 列出选修1号课的学生姓名及成绩

    复制代码
    SELECT 姓名, 成绩
    FROM 学生, 选课
    WHERE 学生.学号 = 选课.学号 AND 课号 = '1';

    等价写法

    复制代码
    SELECT 姓名, 成绩
    FROM 学生
    INNER JOIN 选课 ON 学生.学号 = 选课.学号
    WHERE 课号 = '1';
  2. 列出选修1号课的学生的学号、姓名及成绩

    复制代码
    SELECT 学生.学号, 姓名, 成绩
    FROM 学生, 选课
    WHERE 学生.学号 = 选课.学号 AND 课号 = '1';

    等价写法

    复制代码
    SELECT 学生.学号, 姓名, 成绩
    FROM 学生
    INNER JOIN 选课 ON 学生.学号 = 选课.学号
    WHERE 课号 = '1';

3. 分组聚合查询

知识点讲解
  • GROUP BY:用于对结果集进行分组,通常与聚合函数(如 SUM, COUNT, AVG 等)一起使用。
  • HAVING:用于过滤分组后的结果集。
  • SUM 函数:计算指定列的总和。
SQL 代码示例
  • 求出总分大于150的学生的学号、姓名及总成绩

    复制代码
    SELECT 学生.学号, 姓名, SUM(成绩) AS 总成绩
    FROM 学生, 选课
    WHERE 学生.学号 = 选课.学号
    GROUP BY 选课.学号
    HAVING SUM(成绩) > 150;

    等价写法

    复制代码
    SELECT 学生.学号, 姓名, SUM(成绩) AS 总成绩
    FROM 学生
    INNER JOIN 选课 ON 学生.学号 = 选课.学号
    GROUP BY 选课.学号
    HAVING SUM(成绩) > 150;

++为什么这里要用到GROUP BY?++

  1. GROUP BY 的作用:

    • 将结果集按指定的列(或多个列)进行分组。
    • 在本例中,按 选课.学号 分组,即对每个学生的选课记录进行分组。
  2. SUM(成绩) 的作用:

    • 对每个分组中的 成绩 列进行求和。
    • 如果没有 GROUP BYSUM(成绩) 会计算整个表的 成绩 总和,而不是每个学生的总成绩。
  3. HAVING 的作用:

    • 用于过滤分组后的结果集。
    • 在本例中,筛选出总成绩大于 150 的学生。
  4. 为什么需要 GROUP BY

    • 如果不使用 GROUP BY,查询会报错,因为 SUM(成绩) 是一个聚合函数,而 学生.学号姓名 是非聚合列,SQL 无法确定如何将这两者关联。
    • GROUP BY 明确指定了按 选课.学号 分组,从而可以正确计算每个学生的总成绩。

示例数据

假设 学生 表数据如下:

学号 姓名
1 张三
2 李四
3 王五

选课 表数据如下:

学号 课号 成绩
1 1 80
1 2 90
2 1 70
2 2 60
3 1 85
3 2 95

查询结果

执行上述查询后,结果将是:

学号 姓名 总成绩
1 张三 170
3 王五 180
  1. 学号 = 1
    • 成绩:80 + 90 = 170。
    • 总成绩大于 150,符合条件。
  2. 学号 = 2
    • 成绩:70 + 60 = 130。
    • 总成绩不大于 150,不符合条件。
  3. 学号 = 3
    • 成绩:85 + 95 = 180。
    • 总成绩大于 150,符合条件。

4. 连接查询的注意事项

  1. 明确连接条件:连接查询必须指定表之间的关联列,否则会产生笛卡尔积(Cartesian Product),导致结果集过大。

  2. 使用表别名 :当表名较长或查询涉及多个表时,可以使用表别名简化代码。

    复制代码
    SELECT s.学号, s.姓名, c.成绩
    FROM 学生 AS s
    INNER JOIN 选课 AS c ON s.学号 = c.学号
    WHERE c.课号 = '1';
  3. 避免歧义列名 :如果多个表中有相同的列名,必须使用表名或别名限定列名,例如 学生.学号


5. 连接查询的综合应用

示例:查询每个学生的总成绩及平均成绩
复制代码
SELECT 学生.学号, 姓名, SUM(成绩) AS 总成绩, AVG(成绩) AS 平均成绩
FROM 学生
INNER JOIN 选课 ON 学生.学号 = 选课.学号
GROUP BY 学生.学号, 姓名;
示例:查询选修了1号课和2号课的学生
复制代码
SELECT 学生.学号, 姓名
FROM 学生
INNER JOIN 选课 AS c1 ON 学生.学号 = c1.学号 AND c1.课号 = '1'
INNER JOIN 选课 AS c2 ON 学生.学号 = c2.学号 AND c2.课号 = '2';

假设还有一个 courses 表,包括 course_id (课程ID) 和 student_id (学生ID)

6.3 自连接 (SELF JOIN)

1. 列出专业相同的学生姓名及专业信息

复制代码
SELECT a.姓名, b.姓名, 专业
FROM 学生 a, 学生 b
WHERE a.学号 <> b.学号 AND a.专业 = b.专业;
知识点讲解
  1. 自连接(SELF JOIN)​

    • 学生 表与自身连接,生成两个实例 ab
    • 通过 a.学号 <> b.学号 确保排除同一个学生。
    • 通过 a.专业 = b.专业 筛选出专业相同的学生。
  2. 查询逻辑

    • 学生 表中选取两个实例 ab
    • 筛选出学号不同但专业相同的学生。
    • 返回这些学生的姓名及专业信息。
示例数据

假设 学生 表数据如下:

学号 姓名 专业
1 张三 软件
2 李四 网络
3 王五 软件
4 赵六 电子
查询结果
姓名 姓名 专业
张三 王五 软件
王五 张三 软件

2. 求至少选修1号课和2号课的学生的学号

SQL 查询语句
复制代码
SELECT X.学号
FROM 选课 X, 选课 Y
WHERE X.学号 = Y.学号 AND X.课号 = "1" AND Y.课号 = "2";
知识点讲解
  1. 自连接(SELF JOIN)​

    • 选课 表与自身连接,生成两个实例 XY
    • 通过 X.学号 = Y.学号 确保是同一个学生。
    • 通过 X.课号 = "1"Y.课号 = "2" 筛选出同时选修1号课和2号课的学生。
  2. 查询逻辑

    • 选课 表中选取两个实例 XY
    • 筛选出同一个学生(X.学号 = Y.学号),且选修了1号课(X.课号 = "1")和2号课(Y.课号 = "2")。
    • 返回这些学生的学号。
示例数据

假设 选课 表数据如下:

学号 课号 成绩
1 1 85
2 1 75
3 1 90
1 2 88
3 2 95
4 2 80
查询结果
学号
1
3

6.2 左连接 (LEFT JOIN)

复制代码
SELECT students.name, courses.course_name
FROM students
LEFT JOIN courses ON students.id = courses.student_id;

7.嵌套查询

7.1. 嵌套查询的基本概念

  • 嵌套查询:在一个查询中嵌套另一个查询,通常用于解决复杂的查询需求。
  • 子查询 :嵌套在查询中的查询,可以出现在 SELECTFROMWHEREHAVING 子句中。
  • 常用运算符
    • IN:用于匹配子查询的结果。
    • EXISTS:用于检查子查询是否返回结果。
    • ANY/ALL:用于比较子查询的结果。

​7.2 嵌套查询的示例

示例 1:列出选修汇编语言课的学生的学号

方法一 :使用 IN 子查询

复制代码
SELECT 学号
FROM 选课
WHERE 课号 IN (SELECT 课号 FROM 课程 WHERE 课名 = "汇编语言");

方法二 :使用 EXISTS 子查询

复制代码
SELECT 学号
FROM 选课
WHERE EXISTS (SELECT * FROM 课程 WHERE 课名 = "汇编语言" AND 选课.课号 = 课程.课号);
  • IN 子查询:
    • 子查询返回一个值列表,主查询筛选出匹配这些值的记录。
    • 适用于子查询返回结果较少的情况。
  • EXISTS 子查询:
    • 子查询返回一个布尔值(TRUEFALSE),主查询根据布尔值筛选记录。
    • 适用于子查询返回结果较多或需要关联主查询的情况。

示例 2:求软件专业所有必修课的课程信息

方法一 :使用 IN 子查询

复制代码
SELECT *
FROM 课程
WHERE 课号 IN (SELECT 课号 FROM 必修课 WHERE 必修专业 = "软件");

方法二 :使用 EXISTS 子查询

复制代码
SELECT *
FROM 课程
WHERE EXISTS (SELECT * FROM 必修课 WHERE 必修专业 = "软件" AND 课程.课号 = 必修课.课号);

示例3:求选修2号课的学生中,成绩比选修1号课的最低成绩要高的学生的学号和成绩

方法一:使用子查询

复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 = "2" AND 成绩 > (
    SELECT MIN(成绩)
    FROM 选课
    WHERE 课号 = "1"
);

解题思路

  1. 子查询 :获取选修1号课的最低成绩。

    复制代码
    SELECT MIN(成绩) FROM 选课 WHERE 课号 = "1";
  2. 主查询 :筛选出选修2号课且成绩高于子查询结果的学生。

    复制代码
    SELECT 学号, 成绩 FROM 选课 WHERE 课号 = "2" AND 成绩 > (子查询结果);
方法二:使用 ANY 关键字
复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 = "2" AND 成绩 > ANY (
    SELECT 成绩
    FROM 选课
    WHERE 课号 = "1"
);

解题思路

  1. 子查询 :获取选修1号课的所有成绩。

    复制代码
    SELECT 成绩 FROM 选课 WHERE 课号 = "1";
  2. 主查询 :筛选出选修2号课且成绩高于子查询中任意一个成绩的学生。

    复制代码
    SELECT 学号, 成绩 FROM 选课 WHERE 课号 = "2" AND 成绩 > ANY (子查询结果);

示例4:求选修2号课的学生中,成绩比选修1号课的任何学生的成绩都要高的那些学生的学号和成绩
方法一:使用子查询
复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 = "2" AND 成绩 > (
    SELECT MAX(成绩)
    FROM 选课
    WHERE 课号 = "1"
);

解题思路

  1. 子查询 :获取选修1号课的最高成绩。

    复制代码
    SELECT MAX(成绩) FROM 选课 WHERE 课号 = "1";
  2. 主查询 :筛选出选修2号课且成绩高于子查询结果的学生。

    复制代码
    SELECT 学号, 成绩 FROM 选课 WHERE 课号 = "2" AND 成绩 > (子查询结果);
方法二:使用 ALL 关键字
复制代码
SELECT 学号, 成绩
FROM 选课
WHERE 课号 = "2" AND 成绩 > ALL (
    SELECT 成绩
    FROM 选课
    WHERE 课号 = "1"
);

解题思路

  1. 子查询 :获取选修1号课的所有成绩。

    复制代码
    SELECT 成绩 FROM 选课 WHERE 课号 = "1";
  2. 主查询 :筛选出选修2号课且成绩高于子查询中所有成绩的学生。

    复制代码
    SELECT 学号, 成绩 FROM 选课 WHERE 课号 = "2" AND 成绩 > ALL (子查询结果);

示例5列出每门课程中成绩最高的选课信息
复制代码
SELECT *
FROM 选课 A
WHERE 成绩 = (
    SELECT MAX(成绩)
    FROM 选课 B
    WHERE A.课号 = B.课号
);
知识点讲解
  1. 嵌套查询
    • 在主查询中嵌套了一个子查询。
    • 子查询的作用是找到每门课程的最高成绩。
  2. 子查询逻辑
    • SELECT MAX(成绩) FROM 选课 B WHERE A.课号 = B.课号
      • 选课 表(别名 B)中找到与主查询当前记录(A.课号)相同的课程的最高成绩。
  3. 主查询逻辑
    • 选课 表(别名 A)中筛选出成绩等于子查询结果的记录,即每门课程中成绩最高的选课信息。

示例6: 列出每个学生中成绩低于本人平均成绩的选课信息
复制代码
SELECT *
FROM 选课 A
WHERE 成绩 < (
    SELECT AVG(成绩)
    FROM 选课 B
    WHERE A.学号 = B.学号
);
知识点讲解
  1. 嵌套查询
    • 在主查询中嵌套了一个子查询。
    • 子查询的作用是计算每个学生的平均成绩。
  2. 子查询逻辑
    • SELECT AVG(成绩) FROM 选课 B WHERE A.学号 = B.学号
      • 选课 表(别名 B)中找到与主查询当前记录(A.学号)相同的学生的平均成绩。
  3. 主查询逻辑
    • 选课 表(别名 A)中筛选出成绩低于子查询结果的记录,即每个学生中成绩低于本人平均成绩的选课信息。

7.​3. 嵌套查询的注意事项

  1. 子查询的结果

    • 子查询必须返回一个值或一组值,以便主查询使用。
    • 例如:IN 子查询必须返回一个值列表,EXISTS 子查询必须返回一个布尔值。
  2. 子查询的性能

    • 子查询可能会影响查询性能,尤其是在数据量较大时。
    • 优化子查询的方法包括:
      • 使用索引。
      • 将子查询改写为连接查询。
  3. 子查询的嵌套深度

    • 子查询可以嵌套多层,但嵌套深度过深会增加查询复杂度,降低可读性。

总结

SELECT 语句是 SQL 语言中最重要的查询工具,通过 WHERE 条件筛选,ORDER BY 排序,GROUP BY 聚合,JOIN 连接以及子查询等方式,可以高效地查询和分析数据。通过本文系统地练习,可以打定深厚的 SQL 学习基础。

综合练习主页接

相关推荐
OnlyEasyCode4 小时前
Navicat 任务自动备份指定数据库
数据库
if else4 小时前
Redis 哨兵集群部署方案
数据库·redis
yejqvow124 小时前
Pandas 高效实现组内跨行时间戳匹配与布尔标记
jvm·数据库·python
了不起的云计算V4 小时前
从DeepSeek V4适配看国产算力的三个拐点
数据库·人工智能
qq_189807034 小时前
html标签如何提升可访问性_aria-label与title区别【指南】
jvm·数据库·python
norq juox4 小时前
MySQL 导出数据
数据库·mysql·adb
qq_349317485 小时前
mysql如何设置定时自动备份脚本_编写shell脚本与cron任务
jvm·数据库·python
952365 小时前
Spring IoC&DI
java·数据库·spring
尚雷55805 小时前
从电商订单支付更新,吃透 Oracle 数据修改的底层设计哲学与全组件协同原理
数据库·oracle
2401_832365525 小时前
Chart.js 4 中基于数据实际范围的线性渐变填充方案
jvm·数据库·python