- 前言 ❓
- 单表查询
- 选择表中的若干列
- 查询经过计算的值
- 选择表中的若干元组(行)
- 消除取值重复的行
- 查询满足条件的元组(WHERE)
- 对查询结果排序(ORDER BY)
- 聚集函数
- 对查询结果分组(GROUP BY)
- 感谢 💖
本篇文章创作总时间: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 |
- 比较大小
例:查询计算机系的所有学生的学号和姓名:
SELECT Sno,Sname
FROM Student
WHERE Sdept='CS';
例: 查询考试成绩不及格的学生的学号:
SELECT Sno
FROM SC
WHERE Grade<60;
/*等价于:*/
SELECT Sno
FROM SC
WHERE NOT Grade>=60;
- 确定范围
例:查询年龄在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;
- 确定集合
例:查询信息系(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';
-
字符匹配(模糊查询)
- % (百分号):代表任意长度(长度可以为0)的字符串
- _(下横线):代表任意单个字符
- 当用户要查询的字符串本身就含有 % 或 _ 时,要使用ESCAPE ‘<换码字符>’ 短语对通配符进行转义
例:查询所有姓张的、第3个字为“伟”的学生的姓名,学号和性别:
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE '张__伟%';
例:查询DB_Design课程的课程号及学分:
SELECT *
FROM Course
WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';
- 涉及空值的查询
例:查询所有有成绩的学生学号和课程号:
SELECT Sno,Cno
FROM SC
WHERE Grade IS NOT NULL;
- 基于多个条件的查询
例:查询计算机系年龄在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子句中不能包含。
感谢 💖
好啦,这次的分享就到这里,感谢大家看到这里🤞