本篇主要总结基于单表的查询,内容涉及去重查找,条件查询,模糊查询,分组查询等内容。测试结果一律采用先显示SQL语句,再显示测试结果(以图片的形式进行展现)的方式。
一、准备工作

本次的所有操作都将基于三张表,分别是学生表(Student),课程表(Course),学生选课表(SC)。具体建表语句这里不再赘述,直接给出表中数据内容。

1.学生表(Student)

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表

2.课程表(Course)

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_02

3.学生选课表(SC)

mysql单表查询课程表 sql查询课程表的所有信息_元组_03

二、单表查询——仅涉及一个表的查询
0.查询的一般格式为:

select (distinct) 目标列表达式
from 表名或视图名
where 条件表达式
group by 列名 having 条件表达式
order by ASC|DESC

1.选择表中的若干列
(1)查询指定列(这里回顾了上篇内容,其实上一篇已经写过)

例1:查询全体学生的学号和姓名。其中各个列的先后顺序可以自己根据需要决定,没有硬性规定。

select Sno,Sname
from Student;

mysql单表查询课程表 sql查询课程表的所有信息_Sage_04


例2:查询全体学生的姓名、学号、所在系。

select Sname,Sno,Sdept
from Student;

mysql单表查询课程表 sql查询课程表的所有信息_Sage_05

(2)查询全部列

方式一:列出所有的列名

select Sno,Sname,Ssex,Sage,Sdept
from Student;

方式二:使用通配符*

select *
from Student;

可以发现,二者结果是一样的,不过*的查询结果是和建表时的列名出现的顺序是一致的,而自己列出所有的列名时,可以自定义各个列的顺序。

mysql单表查询课程表 sql查询课程表的所有信息_元组_06

(3)查询经过计算的值

select子句的目标表达式不仅可以是表中的属性列,也可以是表达式
例1:查询全体学生的姓名及其出生年份
Student表中实际存储的是学生的年龄,即Sage,要查询出生年份,可以使用计算,即用当前的年份-学生的年龄

select Sname,2021-Sage
from Student

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_07


容易发现,当前的出生年份的查询结果没有显示列名,但实际上我们可以给它指定一个列名,这里我为该列命名为Birth

select Sname,2021-Sage as Birth
from Student

mysql单表查询课程表 sql查询课程表的所有信息_Sage_08


目标列的表达式不仅可以是算术表达式,还可以是字符串常量、函数等

例2:查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名。

补充:起别名,由于直接写最终的结果会显示无列名,所以可以通过在查询内容后加一个空格或者使用as关键字,之后加所起的名字即可。

select Sname,'Year of Birth' as 'Year of Birth',2021-Sage as Birth,LOWER(Sdept)as Sdept
from Student;

可以发现,系名全都变成了小写

mysql单表查询课程表 sql查询课程表的所有信息_元组_09

相应的,可以转换为小写,就可以转换成大写,这里在小写的基础上进行转换。转换后,可以发现所有的系名已经由小写全部转换为大写

select Sname,'Year of Birth' as 'Year of Birth',2021-Sage as Birth,UPPER(Sdept)as Sdept
from Student;

mysql单表查询课程表 sql查询课程表的所有信息_Sage_10

2.选择表中的若干元组
(1)消除取值重复的行

两个本来并不完全相同的元组在投影到指定的某些列上后,可能会变成相同的行,可以使用distinct关键字来消除它们。
例1:查询选修了课程的学生学号

select Sno
from SC;

mysql单表查询课程表 sql查询课程表的所有信息_元组_11


上述查询结果中包含了许多重复的行,出现的原因是一个人可以选不止一门的课程,为了去掉重复的行,使用关键字distinct

select distinct Sno
from SC;

mysql单表查询课程表 sql查询课程表的所有信息_元组_12


如果没有distinct,则默认是all,即查询所有,查询的结果和不加all,也不加distinct的结果是一样的。

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_13

(2)查询满足条件的元组——通过where子句实现

常用的查询条件如下

查询条件

谓词

比较

=,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符

确定范围

BETWEEN AND , NOT BETWEEN AND

确定集合

IN,NOT IN

字符匹配

LIKE,NOT LIKE

空值

IS NULL,NOT IS NULL

多重条件

AND,OR,NOT

①比较大小

例1:查询计算机科学系全体学生的名单

select Sname
from Student
where Sdept='CS';

mysql单表查询课程表 sql查询课程表的所有信息_元组_14


例2:查询所有年龄在20岁以下的学生姓名及其年龄

select Sname,Sage
from Student
where Sage<20;

mysql单表查询课程表 sql查询课程表的所有信息_元组_15


例3:查询考试成绩不及格的学生的学号(由于一个学生可能不止一科不及格,所以使用了distinct关键字来去重)

select distinct Sno
from SC
where Grade<60;

查询结果为空,说明没有不及格的学生

mysql单表查询课程表 sql查询课程表的所有信息_升序_16

②确定范围

谓词BETWEEN···AND···和NOT BETWEEN ··· AND···可以用来查找属性在某个范围内的元组,其中BETWEEN后的是范围的下限,即低值,AND后的是范围的上限,即高值。
例1:查询年龄在20-23(包括20和23)之间的学生的姓名、系别和年龄

select Sname,Sdept,Sage
from Student
where Sage between 20 and 23;

mysql单表查询课程表 sql查询课程表的所有信息_升序_17


例2:查询年龄不在20-23之间的学生姓名、系别和年龄

select Sname,Sdept,Sage
from Student
where Sage not between 20 and 23;

mysql单表查询课程表 sql查询课程表的所有信息_元组_18

③确定集合

谓词IN可以用来查找属性值属于指定集合的元组。
例1:查询计算机科学系(CS),数学系(MA)和信息系(IS)学生的姓名和性别

select Sname,Ssex
from Student
where Sdept in('CS','MA','IS');

mysql单表查询课程表 sql查询课程表的所有信息_元组_19


与IN相对的是NOT IN,即不在指定集合中的元组

④字符匹配(模糊查询)

使用关键字like(not like),后面是响应的匹配,可以使用通配符%或者_
%(百分号)代表任意长度(长度可以为0)的字符串
下横线代表任意单个字符,长度有限制,即有多少个下横线就代表最多可以匹配的字符数
例1:查询所有姓刘的学生的姓名、学号和性别

select Sname,Sno,Ssex
from Student
where Sname like '刘%';

mysql单表查询课程表 sql查询课程表的所有信息_升序_20


例2:查询姓欧阳且全名为三个汉字的学生的姓名(由于之前建的表中没有,这里新添了三条有关欧阳的数据)

我的不知道为啥,不能正常显示,我需要打8个下横线才会正常显示,少于8个,一个都不显示,还没找到合适的解决办法,但是%可以正常使用

select Sname
from Student
where Sname like '欧阳________';

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_21


例3:查询名字中第二个字为“阳”的学生的姓名和学号(这个的下横线又可以正常使用了,好奇怪。。。。)

select Sname,Sno
from Student
where Sname like '_阳%';

mysql单表查询课程表 sql查询课程表的所有信息_元组_22


例4:查询所有不姓刘的学生的姓名、学号和性别

select Sname,Sno,Ssex
from Student
where Sname not like '刘%';

mysql单表查询课程表 sql查询课程表的所有信息_Sage_23


如果要查询的字符串本身就含有通配符%或_,这时就要使用ESCAPE '<换码字符>'短语对通配符进行转义了

例5:查询DB_Design课程的课程号和学分(在Course表中插入该课程,用于测试)

escape ''表示“\”为换码字符,这样匹配后它会将下横线转义为普通的下横线字符。

select Cno,Ccredit
from Course
where Cname like 'DB\_Design' escape '\';
⑤涉及空值的查询

例1:某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩,查询缺少成绩的学生的学号和相应的课程号(插入一条这样的数据)

==PS:==这里的is绝对不可以用=代替!!!

select Sno,Cno
from SC
where Grade is null;

mysql单表查询课程表 sql查询课程表的所有信息_元组_24

⑥多重条件查询

逻辑运算符AND和OR可用来连接多个查询条件,AND的优先级高于OR,但可以用括号改变优先级
例1:查询计算机科学系年龄在20岁以下的学生姓名

select Sname
from Student
where Sdept='CS' and Sage<20;

mysql单表查询课程表 sql查询课程表的所有信息_Sage_25


IN谓词实际上是多个OR运算符的缩写,因此前边的IN运算符的测试的SQL语句可以更改为

select Sname,Ssex
from Student
where Sdept='CS' or Sdept='MA' or Sdept='IS';
3.ORDER BY子句

可以使用order by子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认为升序
例1:查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列

select Sno,Grade
from SC
where Cno=3
order by Grade desc;

mysql单表查询课程表 sql查询课程表的所有信息_Sage_26


对于空值,排序时显示的次序由具体的系统实现决定,若为升序,则空值在最后,若为降序,则空值在最前边

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

select *
from Student
order by Sdept,Sage desc;

mysql单表查询课程表 sql查询课程表的所有信息_元组_27

4.聚集函数
①count()统计元组个数

例1:查询学生总数

select count(*)
from Student;

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_28


例2:查询选修了课程的学生人数(去重之后的,因为一个学生可以选修多门课程,而这里主要是统计都有谁选课了)

select count(distinct Sno)
from SC;

mysql单表查询课程表 sql查询课程表的所有信息_升序_29

②AVG()计算一列值的平均值

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

select avg(Grade)
from SC
where Cno=1;

mysql单表查询课程表 sql查询课程表的所有信息_升序_30

③MAX()计算某一列的最大值

例::查询选修1号课程的学生最高分数

select max(Grade)
from SC
where Cno=1;

mysql单表查询课程表 sql查询课程表的所有信息_元组_31

④SUM求某一列值的总和

例:查询学生201215121选修课程的总学分数

select sum(Ccredit)
from SC,Course
where Sno='201215121'and SC.Cno=Course.Cno

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_32

5.GROUP BY子句

该子句将查询结果按某一列或多列的值分组,值相等的为一组,分组后聚集函数将作用于每一个组,即每一个组都有一个函数值
例:求各个课程号及相应的选课人数

select Cno,count(Sno)
from SC
group by Cno;

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_33


该语句对查询结果按照Cno的值分组,所有具有相同Cno值的元组为一组,然后对每一组作用聚集函数count进行计算,以求得该组的学生人数。如果分组后还要求按一定的条件对这些组进行筛选,可以使用having短语指定筛选条件

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

select Sno
from SC
group by Sno
having count(*)>=3;

mysql单表查询课程表 sql查询课程表的所有信息_mysql单表查询课程表_34

6.遇到的问题:

模糊查询中的下横线通配符无法正常使用,百度查了好久,还没有看到合适的解决办法,希望尽快找到解决办法。