一、前言
这学期在上《数据库原理及其应用》这门课,我觉得非常有趣!感觉才学了几节课就已经对数据库有了更深的理解,包括数据库的关系代数语言、SQL语言、关系数据库的设计等等,这使我马上写了个教务管理系统练练手,并且特意研究设计了多个关系表及其之间的联系,然后建表,创建视图。对于这个项目我之后应该会另发文章介绍,目前写的第一版是用SSM框架 jsp,之后会使用vue框架 springboot改成前后端分离版。
咳咳,偏离主题了!今天我来给大家分享一些我在做SQL查询实验时,大脑不经意间总结出的一些小套路!
众所周知,想实现对一个或多个数据表信息的查询需求,可以用多种的SQL语句形式实现。但是我发现有一种套路是接近万能的!如果你还不熟悉SQL的查询语句,那不妨继续看下去叭!
话不多说,上干货!
二、套路
- 观察题目需求, 找到最后要求我们展示的所有属性, 并先写下
select attr1, attr2 ...
2. 看这些属性分别来自于哪些表, 然后把所有涉及到的表名称写到from 后面(下面假设涉及多表)
代码语言:javascript复制select attr1, attr2 .... from table1, table2 ...
3. 然后再毫不犹豫地在where后面加上各个表的外键属性相等的条件(原理之后介绍)
代码语言:javascript复制select attr1, attr2.... from table1, table2... where table1.Tno = table2.Tno (and ....)
4. 这时候, 如果题目是简单查询, 那你只用再and上一个或几个条件就好了
代码语言:javascript复制select attr1, attr2.... from table1, table2... where table1.Tno = table2.Tno (and ....)
and table1.Tno = val (and ...)
但是有时候题目往往不会很简单, 可能会涉及到嵌套子查询, 那我们就要搬出我们万能的exists和not exists了, 众所周知, 所有谓词的条件都能用这两个来代替。
但是exists和not exists里的子查询,也会是完整的select语句,只是属性不用罗列,写上select * 罢了,但是如果子查询涉及到多个表,那还是只用重复以上的步骤,where上多表之间外键相等的条件,然后再根据题目补充条件就好了。
代码语言:javascript复制select attr1, attr2.... from table1, table2... where table1.Tno = table2.Tno (and ....)
and table1.Tno = val (and ...) and exists(
select * from table3, table4 ... where table3.Tno = table4.Tno (and ...)
)
到这里是不是看上去感觉有点道理,但是没有很深刻的理解呢?不要着急,下面会上例题!
首先解释一下这个套路的合理性,select罗列所有要展示的属性这是必然的,不用多说,而where上外键相等的条件,可能你们在做题时,会不假思索地写上,但是没总结过这是绝对要写的。
因为如果不where上多表之间的外键相等关系,查出来的数据只是多表的笛卡尔积,但是两个关系表在1对1和1对多的关系中(多对多会创建中间表,而每个表和中间表之间也是1对多的关系),一个关系表的元组,肯定是靠它的外键,在另一个关系表中找到和自己有关联的元组信息,而其他没关联的应被舍去。所以外键相等的条件是必然的。
下面上例题
三、实战
样例的表信息:
1.Wangyb_Courses
2.Wangyb_Reports
3.Wangyb_Students
4.Wangyb_Teachers
1.简单查询
(1)查询学号S52的学生的姓名和选修的课程名称及成绩。
1. 首先按照最后要展示的属性,写出
代码语言:javascript复制Select wyb_Sname, wyb_Cname, wyb_Score
2. 发现涉及到三个表,则接上
代码语言:javascript复制From Wangyb_Students S, Wangyb_Courses C, Wangyb_Reports R
3. 因为涉及多表,话不多说,接上外键属性相等的条件
代码语言:javascript复制Where S.wyb_Sno = R.wyb_Sno and C.wyb_Cno = R.wyb_Cno
4. 再接上题目剩下的一个条件
代码语言:javascript复制And S.wyb_Sno = ‘S52’
这种题就这样被解决了。至于复杂的题目,其实也只是在第3步的基础上and上一个exists或者not exists,在括号中select * from table1, table2,再where上多表的外键相等的条件,再根据题目and上补充的条件即可。
2.复杂查询
(1)查询没有学生选的课程的编号和名称。
1. 首先按照最后要展示的属性,写出
代码语言:javascript复制Select wyb_Cno, wyb_Cname
2. 发现只涉及一个表
From Wangyb_Courses
3. 因为题目的需求的不能直接补充and上一个简单条件出来,所以要涉及exists或者not exists
代码语言:javascript复制Where not exists(
* 3.1 因为要找出没有学生选的课涉及Wangyb_Students, Wangyb_Reports两个表,那么也一样,外键相等,
Select * from Wangyb_Students S, Wangyb_Reports R where S.wyb_Sno = R.wyb_Sno
* 3.2 再and上补充条件
and R.wyb_Cno = wyb_Cno
)
最后,完整的语句就是
代码语言:javascript复制Select wyb_Cno, wyb_Cname from Wangyb_Courses where not exists(
Select * from Wangyb_Students S, Wangyb_Reports R where S.wyb_Sno = R.wyb_Sno and R.wyb_Cno = wyb_Cno
)
(2)查询所有选了“数据库原理及其应用”课程的学生编号和姓名。
1. 首先按照最后要展示的属性,写出
代码语言:javascript复制Select wyb_Sno, wyb_Sname
2. 发现只涉及一个表
代码语言:javascript复制from Wangyb_Students S
3. 因为题目的需求的不能直接补充and上一个简单条件出来,所以要涉及exists或者not exists
代码语言:javascript复制where exists(
* 3.1 因为要找出没有学生选的课涉及Wangyb_Courses, Wangyb_Reports两个表,那么也一样,外键相等,
Select * from Wangyb_Reports R, Wangyb_Courses C where R.wyb_Cno = C.wyb_Cno
* 3.2 再and上补充条件
and C.wyb_Cname = '数据库原理及其应用' and S.wyb_Sno = R.wyb_Sno
)
(3)查询选修了所有课程的学生姓名。(多级嵌套)
这道题在SQL查询中会比较特殊,因为SQL没有直接的语法支持全部,所有等全称量词的查询,所以只能转换思路,查询"没有一个课程这个学生没选的学生姓名", 这里会比较难以理解,一定要先把这个转换搞懂!
1. 首先按照最后要展示的属性,写出
代码语言:javascript复制Select wyb_Sname
2. 发现只涉及一个表
代码语言:javascript复制from Wangyb_Students S
3. 因为题目的需求的不能直接补充and上一个简单条件出来,所以要涉及exists或者not exists
代码语言:javascript复制where not exists(
select * from Wangyb_Courses C
* 3.1 据题意,还得where一层not exists
where not exists(
* 3.2 这里只涉及单表,
Select * from Wangyb_Reports R where
* 3.3 再and上补充条件
S.wyb_Sno = R.wyb_Sno and C.Cno = R.wyb_Cno
)
)
四、总结
怎么样!看完后是不是感觉再拿到SQL查询题时,就知道从哪里对它下毒手了呢?虽然这个套路好用,但也要建立在对多个关系数据表的查询稍微熟练的前提之上,就比如在查询时会涉及嵌套子查询,而嵌套子查询分为相关子查询和不相关子查询,而相关子查询就会要在where后面根据题目要求and上父查询涉及到的Father_table和子查询涉及到的Child_table之间的属性关系。