【数据库系统概论】数据查询之单表查询。详细解释WHERE、OEDER BY、GROUP BY 和 HAVING

本篇文章创作总时间:1h9min
总字数:3770字
预计阅读时间:10~20min

建议收藏之后慢慢阅读

前言 ❓

SQL提供了SELECT语句进行查询操作。虽然只有这一个查询动词,但它有灵活的使用方式和丰富的功能。

查询的一般格式为:

sql 复制代码
SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>] ...
FROM <表名或视图名>[,<表名或视图名>] ...
[ WHERE <条件表达式> ]
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]
[ ORDER BY <列名2> [ ASC|DESC ] ]
  • SELECT子句:指定要显示的属性列
  • FROM子句:指定查询对象(基本表或视图)
  • WHERE子句:指定查询条件。筛选元组(行)
  • GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用集函数
  • HAVING短语:筛选出只有满足指定条件的组
  • ORDER BY子句:对查询结果表按指定列值的升序或降序排序

单表查询

单表查询只涉及一个表或一个视图,是一种最简单的查询操作。

假设这里有三张表,分别是:

  • 学生表:Student(Sno,Sname,Ssex,Sage,Sdept)
  • 课程表:Course(Cno,Cname,Cpno,Ccredit)
  • 学生选课表:SC(Sno,Cno,Grade)
    以下示例都基于这三张表。

选择表中的若干列

例1:查询全体学生的学号、姓名和所在系的有关信息:

sql 复制代码
SELECT Sno, Sname, Sdept
FROM Student;

例2:查询全体学生的所有信息:

sql 复制代码
SELECT *
FROM Student;
/* 该查询等价于如下查询 :*/
SELECT Sno, Sname, Ssex, Sage, Sdept
FROM Student;

查询经过计算的值

SELECT子句的<目标列表达式>可以是:表中的属性列、算术表达式、字符串常量、函数等。

对于算术表达式、常量、函数名的目标列表达式,通常会起一个别名

例1:查询全体学生的姓名及出生年份:

sql 复制代码
SELECT Sname, 2023-Sage
FROM Student;
/* 这里的 2023-Sage 就是一个算术表达式,可以为它指定一个别名:*/
SELECT Sname, 2023-Sage BIRTHDAY
FROM Student;

选择表中的若干元组(行)

消除取值重复的行

在SELECT子句中使用DISTINCT关键字。

比如从学生选课表中查询选修了课程的学生学号,有的学生可能选修了多门课程,但只显示一次学号。这个时候就需要在查询的时候使用DISTINCT关键字消除重复行。

例1: 查询选修程的学生的学号,并消除重复的学号:

sql 复制代码
SELECT DISTINCT Sno
FROM SC

查询满足条件的元组(WHERE)

使用WHERE子句实现。

WHERE子句常用的查询条件有:

查 询 条 件 谓 词
比较 =,>,<,>=,<=,!=,<>,!>,!<,NOT+上述比较运算符
确定范围 BETWEEN AND,NOT BETWEEN AND
确定集合 IN,NOT IN
字符匹配 LIKE,NOT LIKE
空值 IS NULL,IS NOT NULL
逻辑运算 AND,OR,NOT
  1. 比较大小
    例:查询计算机系的所有学生的学号和姓名:
sql 复制代码
SELECT Sno,Sname
FROM Student
WHERE Sdept='CS';

例: 查询考试成绩不及格的学生的学号:

sql 复制代码
SELECT Sno
FROM SC
WHERE Grade<60;
/*等价于:*/
SELECT Sno
FROM SC
WHERE NOT Grade>=60;
  1. 确定范围
    例:查询年龄在20~23岁之间(包括20岁和23岁)的学生的姓名、所在系和年龄:
sql 复制代码
SELECT Sname, Sdept, Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
/*等价于:*/
SELECT Sname, Sdept, Sage
FROM Student
WHERE Sage>=20 AND Sage<=23;
  1. 确定集合
    例:查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别:
sql 复制代码
SELECT Sname,Ssex
FROM  Student
WHERE Sdept IN ( 'IS','MA','CS' );
/*等价于:*/
SELECT Sname, Ssex
FROM Student
WHERE Sdept='IS' OR Sdept='MA' OR Sdept='CS';
  1. 字符匹配(模糊查询)

    • % (百分号):代表任意长度(长度可以为0)的字符串
    • _(下横线):代表任意单个字符
    • 当用户要查询的字符串本身就含有 % 或 _ 时,要使用ESCAPE '<换码字符>' 短语对通配符进行转义

    例:查询所有姓张的、第3个字为"伟"的学生的姓名,学号和性别:

sql 复制代码
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE '张__伟%';

例:查询DB_Design课程的课程号及学分:

sql 复制代码
SELECT  *
FROM  Course
WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';
  1. 涉及空值的查询
    例:查询所有有成绩的学生学号和课程号:
sql 复制代码
SELECT Sno,Cno
FROM  SC
WHERE  Grade IS NOT NULL;
  1. 基于多个条件的查询
    例:查询计算机系年龄在20岁以下的学生的学号、姓名和性别:
sql 复制代码
SELECT Sno, Sname, Ssex
FROM Student
WHERE Sdept='CS' AND Sage<20;

对查询结果排序(ORDER BY)

使用ORDER BY子句,语法格式为:

sql 复制代码
ORDER BY <列名> [ASC | DESC ] [,...]
  • 可以按一个或多个属性列排序
  • 升序:ASC;降序:DESC;缺省值为升序

例:查询全体学生情况,查询结果按所在系的升序排序,同一系中的学生按年龄降序排序:

sql 复制代码
SELECT *
FROM Student
ORDER BY Sdept, Sage DESC;

聚集函数

为了增强检索功能,SQL提供了许多聚簇函数,主要有:

  • COUNT([DISTINCT|ALL] *) 统计元组个数(可以去重后再统计)
  • COUNT([DISTINCT|ALL] <列名>) 统计一列中值的个数
  • SUM([DISTINCT|ALL] <列名>) 计算一列值的总和(此列必须是数值型)
  • AVG([DISTINCT|ALL] <列名>) 计算一列值的平均值
  • MAX([DISTINCT|ALL] <列名>) 计算一列值中的最大值
  • MIN([DISTINCT|ALL] <列名>) 计算一列值中的最小值

注意 ❗❗❗:

WHERE子句是不能用聚集函数作为条件表达式的。聚集函数只能用于SELECT子句和GROUP中的HAVING子句

例:计算选修了2号课程的学生平均成绩:

sql 复制代码
SELECT AVG(Grade) AS '平均成绩' 	/* 起别名 */
FROM SC
WHERE Cno='2';

例:统计选修了课程的学生人数:

sql 复制代码
SELECT COUNT(DISTINCT Sno)
FROM SC;

对查询结果分组(GROUP BY)

GROUP BY子句将查询的结果按指定的列进行分组,即将指定列值相同的元组分为同一个组。目的是细化聚集函数的作用对象。

  • 未对查询结果分组,聚集函数将作用于整个查询结果
  • 对查询结果分组后,聚集函数将分别作用于每个组 ,即相当于每个分组均有一个函数值

例: 查询每门课程的课程号及相应的选课人数:

sql 复制代码
SELECT Cno, COUNT(Sno)
FROM SC
GROUP BY Cno;
  • GROUP BY子句的作用对象是查询的中间结果表
  • 分组方法:按指定的一列或多列值分组,值相等的为一组
  • 使用GROUP BY子句后,SELECT子句的列名列表中只能出现分组属性和集函数

如果要按一定的条件对分组进行筛选,则使用HAVING子句指定筛选条件。

例:查询选修了3门以上课程的学生学号:

sql 复制代码
SELECT Sno
FROM  SC
GROUP BY Sno HAVING COUNT(*)>3;
/* 先根据学生学号进行分组,这样就将同一个学号的元组都放在了一组中,然后进行count(*)统计这个组里有多少行,这就是该学号学生选修的课程数*/

注意 ❗❗❗:
HAVING短语与WHERE子句的区别

  • 作用对象不同。WHERE子句作用于基表或视图,从中选择满足条件的元组; HAVING短语作用于组,从中选择满足条件的组。
  • 执行查询时,WHERE是在分组之前被应用,而HAVING子句中的条件在分组之后被应用。
  • HAVING子句可以在条件中包含聚集函数,但WHERE子句中不能包含。

感谢 💖

好啦,这次的分享就到这里,感谢大家看到这里🤞

相关推荐
叁沐8 分钟前
MySQL 07 行锁功过:怎么减少行锁对性能的影响?
mysql
Java烘焙师33 分钟前
架构师必备:业务扩展模式选型
mysql·elasticsearch·架构·hbase·多维度查询
飞翔的佩奇44 分钟前
Java项目:基于SSM框架实现的忘忧小区物业管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
java·数据库·mysql·vue·毕业设计·ssm框架·小区物业管理系统
@Ryan Ding1 小时前
MySQL主从复制与读写分离概述
android·mysql·adb
亚马逊云开发者1 小时前
全景解读亚马逊云科技的 GenBI 解决方案:三大路径助力企业智能决策升级
sql·llm
ZWZhangYu7 小时前
LangChain 构建向量数据库和检索器
数据库·langchain·easyui
feifeigo1238 小时前
升级到MySQL 8.4,MySQL启动报错:io_setup() failed with EAGAIN
数据库·mysql·adb
火龙谷9 小时前
【nosql】有哪些非关系型数据库?
数据库·nosql
焱焱枫10 小时前
Oracle获取执行计划之10046 技术详解
数据库·oracle
双力臂40411 小时前
MyBatis动态SQL进阶:复杂查询与性能优化实战
java·sql·性能优化·mybatis