SELECT单表查询

接上一篇文章中的SELECT语句单表查询。

WHERE子句的条件表达式以及相关谓词:
字符匹配——[NOT] LIKE…[ESCAPE]…

语句:

[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>'];

1.当 匹配串 是一个固定字符串时,这里的LIKE相当于“=”

【例3.29】查询学号为201215121的学生的详细情况。

SELECT * FROM Student WHERE Sno LIKE '201215121';
-- * 表示表中所有属性列值
--等价于
SELECT * FROM Student WHERE Sno = '201215121';

SELECT单表查询_第1张图片
2.匹配串可以包含通配符,也就是模糊查询

通配符:
“%”——代表任意长度(长度可以为0)的字符串。

“_”——代表任意单个字符。

【例3.30】查询所有姓刘同学的姓名、学号和性别。

SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE '刘%';

添加了一些测试数据后,显示出了所有姓刘的同学。
SELECT单表查询_第2张图片
【例3.31】查询姓刘且全名为三个汉字的学生的姓名。

SELECT Sname FROM Student WHERE Sname LIKE '刘__';

SELECT单表查询_第3张图片
唯独没有我们的刘aaa同学,因为它的名字刘后面跟着三个字符,应该对应三个下横线才可以。

用一个下横线:

SELECT Sname FROM Student WHERE Sname LIKE '刘_';

SELECT单表查询_第4张图片
【字符集的问题】

看来我本机用的字符集是GBK~

字符集ASCII —— 一个汉字对应两个字符,即两个_

字符集GBK —— 一个汉字对应一个字符,即一个_

【这里发现了一个奇怪的问题?】

输入一个下横线。查找的是“刘x”,没错。
输入两个下横线,查找的结果应该是三个字的“刘xx”,但是查询的结果中同时有“刘x”和“刘xx”。

但这个并不表示“__”(两个下横线)表示一个或两个字符,它还是表示两个字符的!!

【例】

SELECT Sname FROM Student WHERE Sname LIKE '__a';
--这里是两个下横线

在这里插入图片描述
如果“__”表示一个或两个字符的话,那么结果应该有
刘a,刘aa,但是只有刘aa,表示“_”还是表示一个字符,没有二义。

百度了一下,看到有人说
在这里插入图片描述好像是这样的,在MY SQL中,输入两个下横线查找的结果就是“刘xx”。
这里的差异应该是与数据库有关。

【例3.32】查询名字中第二个字为“阳”的学生的姓名和学号。

SELECT Sname,Sno 
FROM Student 
WHERE Sname LIKE '_阳%';

这里添加了一些测试数据。
SELECT单表查询_第5张图片
【例3.33】查询所有不姓刘的学生姓名、学号和性别。

SELECT Sname,Sno,Ssex
FROM Student 
WHERE Sname NOT LIKE '刘%';

SELECT单表查询_第6张图片
【悄咪咪】发现了一个小细节↓

这里的查询结果都是按照学号Sno排列的哎~

不加ORDER BY子句,查询结果的默认排序??

网上百度了一下:

1.记录顺序是未知的,跟取数据的顺序有关,取数据的顺序取决于执行计划。也就是查询出来的结果无法保证。

2.如果不指定order by 子句,则查询结果的顺序不确定。并不一定是按主键。查询优化器会根据实际情况生成执行计划。排序需要成本的,而且成本可能不小。如果没有明确指定order by子句,则查询结果的顺序不确定。

这样看来,应该只是碰巧按照主码学号排列了。。看起来貌似是个无用的小细节。。。。是我多疑了。
总之,任何时候要排序,就要加ORDER BY子句
(ORDER BY 子句见后)

3.使用换码字符将通配符转义为普通字符。

这种情况涉及到本身字符串中就有下横线_的情况。

【例3.34】查询DB_Design课程的课程号和学分。

SELECT Cno,Ccredit
FROM Course
WHERE Cname LIKE 'DB\_Design' ESCAPE '\';
--最后一定要加ESCAPE,表示出了反斜线的部分为匹配串

SELECT单表查询_第7张图片
【例3.35】查询以“DB_”开头,且倒数第三个字符为i的课程的详细情况。

SELECT * 
FROM Course 
WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';

不加ESCAPE的情况:

SELECT *
FROM Course
WHERE Cname LIKE 'DB\_%i__';

两种情况对比,其中Course表中同时有课程DB_Design和DB\aDeisgn两门课程。
不加ESCAPE,_还是通配符
SELECT单表查询_第8张图片
涉及空值的查询——IS NULL或IS NOT NULL

注意:这里的IS不能用 = 代替。

【例3.36】

SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL;

SELECT Sno,Cno
FROM SC
WHERE Grade = NULL;
--语句没有错误,但结果会出现错误

【例3.37】

SELECT Sno,Cno
FROM SC
WHERE Grade IS NOT NULL;

SELECT单表查询_第9张图片
多重条件查询——AND,OR

AND和OR用来连接多个条件,AND比OR优先级要高。

【例3.38】查询计算机系年龄在20岁以下的学生姓名。

SELECT Sname
FROM Student
WHERE Sdept = 'CS' AND Sage<20;

SELECT单表查询_第10张图片
IN <集合> 可以用OR代替↓
改写【例3.27】

SELECT Sname,Ssex
FROM Student
WHERE Sdept IN('CS','MA');

--等价
SELECT Sname,Ssex
FROM Student
WHERE Sdept='CS' OR Sdept='MA';

SELECT单表查询_第11张图片
结果是一样的。

ORDER BY子句

ORDER BY用于按一个或多个属性列排序,次序有ASC升序和DESC降序,缺省值仍为ASC。

【例3.39】查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。

SELECT Sno,Grade
FROM SC
WHERE Cno='3'
ORDER BY Grade DESC;

对于空值,排序时显示的次序由具体系统实现来决定。
SELECT单表查询_第12张图片
【例3.40】查询全体学生的情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

这里有多个属性列,跟前面的原则一样,先按第一个排列,第一个相同的情况下,按第二个排列。

SELECT *
FROM Student
ORDER BY Sdept,Sage DESC;

SELECT单表查询_第13张图片

聚集函数

SELECT单表查询_第14张图片【例3.41】查询学生总人数

SELECT COUNT(*)
FROM Student;

在这里插入图片描述
【例3.42】查询选修了课程的学生人数

SELECT COUNT(DISTINCT Sno)
FROM SC;

【例3.43】计算1号课程的学生平均成绩

SELECT AVG(Grade)
FROM SC
WHERE Cno='1';

空值肯定不会算在里面的。它也没办法算。。
SELECT单表查询_第15张图片
【例3.44】查询选修2号课程的学生最高分数。(将原题改为了2号课程)

SELECT MAX(Grade)
FROM SC
WHERE Cno='2';

在这里插入图片描述
【例3.45】查询学生201215122选修课程的总学分数。

这个题就要注意了,与后面的多表查询有联系。
敲黑板!!!

这里包含学生选修课程,所以要用到SC表
又要计算学分总和,用到Course表

先将SC表和Course表做一下等值连接SC.Cno=Course.Cno,然后在做选择。

SELECT SUM(Ccredit)
FROM SC,Course
WHERE Sno='201215122' AND SC.Cno = Course.Cno;

下面的表为SC和Course做等值连接后的表。
SELECT单表查询_第16张图片

GROUP BY子句

该子句用于细化上述聚集函数的对象。也就是用于分组。按一列或多列分组,列值相等的为一组。

未分组——聚集函数作用于整个查询结果
分组——聚集函数作用于每个组

【例3.46】求各个课程号及相应的选课人数。

SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno;

(SELECT后面跟所要查询的,FROM后面跟用到的表,这一条以防自己以后看见题犯蒙~)
SELECT单表查询_第17张图片
【例3.47】查询选修了3门课以上的学生学号

SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*)>3;

COUNT(*)统计查询结果中的元组个数。

HAVING 子句作用于组上,必须跟着GROUP BY子句出现,不可单独出现。整体的作用相当于先按GROUP BY 分组,然后根据HAVING后的条件进行筛选组

【例3.48】查询平均成绩大于等于80分的学生学号和平均成绩。

SELECT Sno,AVG(Grade)
FROM SC
WHERE AVG(Grade)>=80
GROUP BY Sno;

以上的做法是错误的!!!

WHERE子句中不能用聚集函数作为条件表达式
这种情况应该用HAVING 子句加条件。

WHERE子句作用于基表或视图
HAVING子句作用于组

正确做法:

SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=80;

SELECT单表查询_第18张图片
单表查询结束啦!!!

【小总结】

SELECT + 要查询的内容
FROM + 用到的表
[WHERE + 筛选条件(包含比较运算符和谓词)]
[ORDER BY + 按照哪些属性列怎样排序(ASC|DESC)]
[GROUP BY + 按照哪些属性列分组]
[HAVING + 筛选组的条件]

DISTINCT用于消去重复元组
ALL显示全部

你可能感兴趣的:(SELECT单表查询)