【数据库】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 学习基础。

综合练习主页接

相关推荐
LJTYBQ29 分钟前
轻松认识 SQL 关键字,打开数据库操作大门
数据库·笔记·sql
山外有山a32 分钟前
从 Neo4j 数据库中提取数据并绘制图谱
数据库·neo4j
Full Stack Developme2 小时前
SQL 版本历史
数据库·sql
杰克逊的日记5 小时前
mysql数据实时全量+增量迁移
数据库·mysql·数据迁移
linuxxx1106 小时前
centos7 升级MariaDB 到 10.5 或更高版本
数据库·mariadb
换个网名有点难6 小时前
django怎么配置404和500
数据库·django
Adellle7 小时前
MySQL
数据库·后端·mysql
就是有点傻7 小时前
C# 中实现一个线程持续读取,另一个线程负责写入,且写入时读取线程暂停
数据库·c#
云观秋毫7 小时前
试试智能体工作流,自动化搞定运维故障排查
运维·数据库·自动化
是沫沫子耶8 小时前
mysql实例
数据库