SQL复杂查询语句
进行多表连接查询,掌握多表连接查询的连接条件或连接谓词,理解内连接、左连接和右连接的含义并熟练操作。
说明:以下实验所用到的表为student,sc,course三张表,分别为学生表,学生课程关系表,课程表,数据已提前建立。
学生表(10条数据)
课程表(7条数据)
学生课程关系表(33条数据)
同时涉及多个表的查询称为连接查询
用来连接两个表的条件称为连接条件或连接谓词
一、 广义笛卡尔积
不带任何连接条件或连接谓词,查询结果行数就是各个表行数的乘积
基本语法:
select table1.column1, table1.column1..., table2.column1, table2.column2..., table3,column1, table3.column2..., ... from table1, table2, table3, ...
例:查询所有学生信息和学生选课课程信息
select student.*, course.* from student, course;
可以看出查询结果是student(10条)表和course(7条)表的随机组合,得到70条数据
我们可以简单统计查询结果的行数,如下所示,结果依然是70
select count(1) from (select student.*, course.* from student, course) a;
注意:这种查询方式很少用,对于不同表的笛卡尔积意义并不大,因为不同表的任意组合表示的含义并不具有实际意义,比如,student和course的笛卡尔积表示每个学生选了每一门课,但实际并不是每个学生都选所有课。
二、 等值连接(含自然连接)和非等值连接
a) 等值连接:连接条件包含“=”
基本语法
select table1.column1, table1.column1..., table2.column1, table2.column2..., table3,column1, table3.column2..., ... from table1, table2, table3, ...
Where table1.column1= table2.column2 [and | or other condition...]
例:查询所有学生选的课程
select student.*, sc.*,course.* from student,sc,course
where student.Sno = sc.Sno and sc.Cno = course.Cno;
可以看出共33条数据,这和sc表的33条数据对应
select count(1) from (select student.Sno, sc.Cno,course.Cname from student,sc,course
where student.Sno = sc.Sno and sc.Cno = course.Cno) a;
b) 非等值连接:连接条件至少有一个条件不包含“=”
基本语法
select table1.column1, table1.column1..., table2.column1, table2.column2..., table3,column1, table3.column2..., ... from table1, table2, table3, ...
Where table1.column1 [>、<、>=、<=、!=] table2.column2 [and | or other condition...]
例:查询学生考试不及格的课程
select student.*, sc.*,course.* from student,sc,course
where student.Sno = sc.Sno and sc.Cno = course.Cno and sc.Grade < 60;
可以看出有两门课程不及格的记录,在表sc中确有两门课程不及格的数据
select sc.* from sc where sc.Grade < 60;
注意:这里我说是两门课程不及格记录,而不是两名学生有不及格课程,这是因为同一个学生选多门课程,有可能一个学生有多门课程不及格。
三、 自身连接查询
一个表与其自己进行连接,称为表的自身连接,由于在同一个查询中,同一个表出现多次,为了区分必须给表起别名。
基本语法:
select t1.column1, t1.column2, ..., t2.column1, t2.column2, ..., ...
from table [as] t1, table [as] t2, ... [where condition]
例:查询每一门课的间接先修课(即先修课的先修课)
select c1.Cno, c1.Cname, c2.Cno spno from course c1,course c2 where c1.Cpno = c2.Cno;
我们可以这样考虑:有两张表分别是c1(当前课程表),c2(先行课程表)其中c1.Cpno表示要上课程c1.Cno要先修c1.Cpno课程,而c1.Cpno课程信息在表c2中记录对应课程号c2.Cno,所以查询条件c1.Cpno = c2.Cno,查询列则是c1.Cno, [c1.Cname, ] c2.Cno表示c1.Cno对应的先行课c2.Cno。
四、 外连接查询
- 普通连接操作只输出满足连接条件的元组
- 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
a) 左连接
左连接是指将左表中的所有数据分别与右表中的每条数据进行连接组合,返回的结果除内连接的数据外,还包括左表中不符合条件的数据,并在右表的相应位置列中添加NULL值。
基本语法:
select table1.column1, table1.column1..., table2.column1, table2.column2... from table1 left [outer] join table2
on table1.column1= table2.column2 [and | or other condition...]
例:course表与sc表左连接
select course.*,sc.* from course left join sc on course.Cno = sc.Cno;
结果显示了34条数据,除了33条是学生选的课程,还有一条是没有任何学生选的课“数据库”。
可以查看一下sc表中是否有Cno=1的数据
select sc.* from sc where sc.Cno = 1;
可以看出sc中确实没有Cno=1的数据
我们在用内连接方式查看一下结果
select course.*, sc.* from course, sc where course.Cno = sc.Cno;
可以看出,查询结果一共33条数据,也就是学生选的课程记录数目,内连接查询并没有把“数据库”这门课所有学生都没有选的课展示出来。
b) 右连接
右连接是指将右表中的所有数据分别与左表中的每条数据进行连接组合,返回的结果除内连接的数据外,还包括右表中不符合条件的数据,并在左表的相应位置列中添加NULL值。
基本语法:
select table1.column1, table1.column1..., table2.column1, table2.column2... from table1 right [outer] join table2
on table1.column1= table2.column2 [and | or other condition...]
例:sc表与course表右连接
select course.*, sc.* from sc right outer join course on course.Cno = sc.Cno;
可以看出未被学生选修的课“数据库”也被显示出来了。
思考:这里我们发现和左连接查询结果相同,这是为什么?这说明了什么现象?
c) 全连接
全连接是指将左表中的所有数据分别与右表中的每条数据进行连接组合,返回的结果除内连接的数据外,还包括左表中不符合条件的数据和右表中不符合条件的数据,并在左表的相应位置列和右表的相应位置列中添加NULL值。
基本语法:
select table1.column1, table1.column1..., table2.column1, table2.column2... from table1 full [outer] join table2
on table1.column1= table2.column2 [and | or other condition...]
注意:mysql不支持全连接
五、 复合条件连接查询
查询条件WHERE子句中含多个连接条件时,称为复合条件连接
基本语法
select table1.column1, table1.column1..., table2.column1, table2.column2..., table3,column1, table3.column2..., ... from table1, table2, table3, ...
Where condition1 and | or condition2 and | or conditon3...
例:查询选课成绩大于90分的学生
select student.*,course.Cno,course.Cname,sc.Grade from student,course,sc
where student.sno = sc.Sno and sc.Cno = course.Cno and sc.Grade > 90;
可用查询条件:
以下格式均在where关键字之后出现
- [NOT] IN关键字,查询某个字段的值是否在[NOT 不在]指定的集合中
格式:
Column IN (value1,value2,...)
(value1,value2,...)可以是单值,也可以是select语句
- BETWEENT AND关键字判断某个字段的值是否在指定范围
格式:
Column BETWEEN value1 AND value2
- LIKE关键字实现模糊查询,它有两个通配符“%”匹配一个或多个字符和“_”只匹配一个字符。
格式:
Column LIKE 匹配字符串
- IS [NOT] NULL关键字判断字段是否为空[NOT 不空]
格式:
Column IS [not] NULL
- AND和OR关键字用来联合查询,AND表示条件同时发生,OR表示至少一个条件发生。
格式:
Condition1 AND | OR condditon2 AND | OR...
- DISTINCT关键字去除查询结果中重复记录,distinct必须放在所有查询字段开头,根据其后的字段组合去重,也就是查询的所有字段组成的元祖视为一体,如果有完全相同的多个元祖则只返回一条
格式:
Select distinct column1, column2, ... from table where condition
- LIMIT关键字限制查询结果的数量
格式:
Select column1, column2, ... from table where condition limit rownum
Rownum表示要限制的行数
也可以从指定行号开始展示指定行数的结果、
格式:
Select column1, column2, ... from table where condition limit rowcode, rownum
Rowcode表示指定的行号,Rownum表示指定行数