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


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

建议收藏之后慢慢阅读

前言 ❓

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

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:查询全体学生的学号、姓名和所在系的有关信息:

SELECT Sno, Sname, Sdept
FROM Student;

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

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

查询经过计算的值

SELECT子句的<目标列表达式>可以是:表中的属性列、算术表达式、字符串常量、函数等。
对于算术表达式、常量、函数名的目标列表达式,通常会起一个别名

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

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

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

消除取值重复的行

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

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

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

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. 比较大小
    例:查询计算机系的所有学生的学号和姓名:
SELECT Sno,Sname
FROM Student
WHERE Sdept='CS';

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

SELECT Sno
FROM SC
WHERE Grade<60;
/*等价于:*/
SELECT Sno
FROM SC
WHERE NOT Grade>=60;
  1. 确定范围
    例:查询年龄在20~23岁之间(包括20岁和23岁)的学生的姓名、所在系和年龄:
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)学生的姓名和性别:
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个字为“伟”的学生的姓名,学号和性别:

SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE '张__伟%';

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

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

对查询结果排序(ORDER BY)

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

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

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

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号课程的学生平均成绩:

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

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

SELECT COUNT(DISTINCT Sno)
FROM SC;

对查询结果分组(GROUP BY)

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

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

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

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

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

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

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

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

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

感谢 💖

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不怕娜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值