首页 > 数据库技术 > 详细

数据库多表查询,请先把我文章的基础知识学会,在钻研难点!!!

时间:2020-06-11 17:06:28      阅读:31      评论:0      收藏:0      [点我收藏+]

多表查询

笛卡尔积

概念:简单来说就是两个集合相乘的结果,集合A和集合B中任意两个元素结合在一起。

缺点:冗杂,得出来的结果并非是想要的,所以需要一种新的应用,将笛卡尔积出来的结果当成一个表格

技术分享图片

/*笛卡尔积*/
SELECT * FROM course,teacher;
-- 给出条件,筛选得到我们所需要的有用的信息
SELECT * FROM course,teacher WHERE course.t_id = teacher.id;
-- 可以给表起别名,方便使用
SELECT * FROM course c,teacher t WHERE c.t_id = t.id;

1、内连接

内连接
内连接查询操作只列出与连接条件匹配的数据行,使用INNER JOIN或者直接使用JOIN 进行连接。

-- 第一种方式,join
select * from Table_A JOIN Table_B;
-- 第二种方式,inner join
select * from Table_A INNER JOIN Table_B;

内连接可以没有连接条件,没有条件之后的查询结果,会保留所有结果(笛卡尔集),与后面分享的交 叉连接差不多。
在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列, 包括其中的重复列

-- 使用了join或者inner join 后面需要跟on进行连接
select * from Table_A AJOIN Table_B B ON A.id = B.id;

查询结果,注意列数是 4 列,两张表的字段直接拼接在一起,重复的字段在后面添加数字序列以做区分

技术分享图片
通俗讲就是根据条件,找到表 A 和 表 B 的数据的交集

技术分享图片
例子:

普通的多表查,课内连接接通相同
SELECT * from teacher t , course c where t.id = c.t_id   (这样会先生成笛卡尔积,效率可能略低)

SELECT * from teacher t JOIN course c on t.id = c.t_id 
SELECT * from teacher t inner JOIN course c on t.id = c.t_id 

结果:只有满足条件的会显示,5号老师没课程,5号课程没老师都不会显示 
1   王宝强 1   数学  1 
2   贾宝玉 2   语文  2 
3   温迪  3   c++ 3 
4   路人甲 4   java    4

2、外连接(常用)

外连接不只列出与连接条件相匹配的行,而且还加上左表(左外连接时)或右表(右外连接时)或两个表(全 外连接时)中所有符合搜索条件的数据行

(1)、左连接(左外连接)

-- 第一种:left join
SELECT * FROM Table_A A LEFT JOIN Table_B B ON A.ID = B.ID
-- 第二种:left outer join
SELECT * FROM Table_A A LEFT OUTER JOIN Table_B B ON A.id = B.id;

查询结果:

技术分享图片

根据条件,用右表(B)匹配左表(A),能匹配,正确保留,不能匹配其他表的字段都置空 Null
也就是,根据条件找到表 A 和 表 B 的数据的交集,再加上左表的数据集, Venn 图表示就是

技术分享图片

红色部分代表查询结果

例子:

SELECT * from teacher t LEFT JOIN course c on t.id = c.t_id 

结果:只有满足条件的会显示,5号老师没课程,依然显示,5号课程没老师都不会显示, 左边表的所有数据都显示
1   王宝强 1   数学  1 
2   贾宝玉 2   语文  2 
3   温迪  3   c++ 3 4   路人甲 
4   java    4 
5   路人乙        

(2)、右连接 (右外连接)

-- 第一种:right join
SELECT * FROM Tabel_A RIGHT JOIN Table_B B ON A.id = B.id;
-- 第二种:right outer join
SELECT * FROM Table_A A RIGHT OUTER JOIN Table_B B ON A.id =B.id;

查询结果:

技术分享图片

根据条件,用左表(A)匹配右表(B),能匹配,正确保留,不能匹配其他表的字段都置空 Null。 也就是,根据条件找到表 A 和 表 B 的数据的交集,再加上右表的数据集, Venn 图表示就是

技术分享图片
例子:

SELECT * from teacher t right JOIN course c on t.id = c.t_id

结果:只有满足条件的会显示,5号老师没课程不显示,5号课程没老师都,依然显示, 右边表的所有数据都显示
1   王宝强  1   数学  1 
2   贾宝玉  2   语文  2 
3   温迪    3   c++ 3 
4   路人甲   4   java    4          
	 	    5    php 

3、全连接,mysql不支持,oracle支持

SELECT * FROM Table_A A FULL JOIN Table_B B ON A.id = B.id;
SELECT * FROM Table_A A FULL OUTER JOIN Table_B B ON A.id = B.id;

目前我的 MySQL 不支持此种方式,可以用其他方式替代解决,在此不展开。

理论上是根据条件找到表 A 和 表 B 的数据的交集,再加上左右表的数据集

技术分享图片

4、子查询

1、where型子查询

将查询结果当条件
例子:查询有一门学科分数大于八十分的学生信息

SELECT * from student where id in (select DISTINCT s_id from scores where score > 90);

-- 等于号的使用
SELECT * FROM student WHERE id = 
(SELECT s_id FROM scores GROUP BY s_id ORDER BY SUM(score) DESC LIMIT 1);

where 型子查询,如果是 where 列 =(内层 sql) 则内层 sql 返回的必须是单行单列,单个值。
where 型子查询,如果是 where 列 in(内层 sql) 则内层 sql 返回的必须是单列,可以多行。

2、from型子查询

在学习 from 子查询之前,需要理解一个概念:查询结果集在结构上可以当成表看,那就可以当成临时 表对他进行再次查询:

取排名数学成绩前五名的学生,正序排列。

-- FROM
-- 取排名数学成绩前五名学生,正序排列
SELECT * FROM student s left JOIN scores e on s.id = e.s_id 
LEFT JOIN course c ON e.c_id = c.id WHERE c.`NAME` = ‘数学‘ 
ORDER BY e.score DESC LIMIT 5;
-- 正序排列
SELECT * FROM (SELECT s.id id,s.name name,e.score score,c.name cname FROM student s LEFT JOIN scores e
ON s.id = e.s_id LEFT JOIN course c ON e.c_id = c.id 
WHERE c.`NAME` = ‘数学‘ ORDER BY e.score DESC LIMIT 5 ) t ORDER BY t.score;

5、练习题

1、查询‘01’号学生的姓名和各科成绩。 *

-- 1、查询‘01’号学生的姓名和各科成绩
SELECT s.name,e.score,c.`NAME` FROM 
student s  LEFT JOIN scores e  on s.id = e.s_id
LEFT JOIN course c on e.c_id = c.id WHERE s.id = ‘1‘;

2、查询各个学科的平均成绩,高成绩。 *

-- 2、查询各个学科的平均成绩,高成绩。
SELECT c.`NAME`,avg(score) ‘平均成绩‘,MAX(score) ‘最高成绩‘
FROM scores s INNER JOIN course c ON c.id = s.c_id
GROUP BY c.`NAME`;

3、查询每个同学的高成绩及科目名称。 *

-- 3、查询每个同学的高成绩及科目名称。
-- 思路:先拿到每个id的最大成绩
SELECT st.id,st.`NAME`,c.`NAME` ‘课程名‘,sc.score ‘最高成绩‘ 
FROM student st LEFT JOIN scores sc on st.id = sc.s_id
LEFT JOIN course c ON sc.c_id = c.id
WHERE sc.score in(
SELECT max(sc.score) FROM scores sc GROUP BY sc.s_id)

4、查询所有姓张的同学的各科成绩。 *

-- 4、查询所有姓张的同学的各科成绩。
SELECT student.id,student.`NAME`,course.`NAME`,scores.score FROM 
student  LEFT JOIN scores ON student.id = scores.s_id  
LEFT JOIN course  on scores.c_id = course.id 
WHERE student.`NAME` LIKE ‘张%‘;

5、查询每个课程高分的同学信息。 *

-- 5、查询每个课程高分的同学信息。
SELECT
	s_id,
	st.age,
	st.gander,
	st. NAME NAME,
	c. NAME project,
	temp.score
FROM
	scores s
INNER JOIN (
	SELECT
		c_id,
		max(score) score
	FROM
		scores
	GROUP BY
		c_id
) temp ON s.c_id = temp.c_id
AND s.score = temp.score
LEFT JOIN student st ON s.s_id = st.id
LEFT JOIN course c ON c.id = temp.c_id;

6、查询名字中含有“张”和‘李’字的学生信息和各科成绩 *

-- 6、查询名字中含有“张”和‘李’字的学生信息和各科成绩
SELECT s.id ‘学号‘,s.name ‘姓名‘,s.age ‘年龄‘,s.gander ‘性别‘,c.`NAME` ‘科目‘,e.score ‘成绩‘
FROM student s LEFT JOIN scores e ON s.id = e.s_id
LEFT JOIN course c on e.c_id = c.id WHERE s.`NAME` LIKE ‘张%‘

7、查询平均成绩及格的同学的信息。*

/*平均成绩
SELECT AVG(score) FROM scores WHERE scores.s_id = ‘7‘;*/
SELECT s.id,s.`NAME`,s.age,s.gander,ROUND(AVG(e.score),2)score
FROM student s LEFT JOIN scores e on s.id = e.s_id GROUP BY s.id
HAVING AVG(e.score )>60

8、将学生按照总分数进行排名。 *

9、查询数学成绩的高分、低分、平均分。

10、将各科目按照平均分排序。 **

11、查询老师的信息和他所带科目的平均分。 **
12、查询被“张楠”和‘‘老孙’叫的课程的高分和平均分。 **

13、查询查询每个同学的好成绩的科目名称。 **

14、查询所有学生的课程及分数。**
15、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名。** 16、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩。 ** 17、查询有不及格课程的同学信息。 **
18、求每门课程的学生人数。 **

19、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列 。 ** *
20、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩。 * **

21、查询有一门课程成绩在90分以上的学生信息; *** ****

22、查询出只有三门课程的全部学生的学号和姓名 ** *
23、查询有不及格课程的课程信息 ** *

24、检索至少选修四门课程的学生学号 * **
25、查询没有学全所有课程的同学的信息 * **
26、查询学全所有课程的同学的信息。 *** *

27、 查询各学生都选了多少门课 ** *
28、查询课程名称为”数学”,且分数低于60的学生姓名和数学分数。 ***

29、查询学过”张楠”老师授课的同学的信息 。*** *

30、查询没学过”张楠”老师授课的同学的信息 * ***

-- 8、将学生按照总分数进行排名。
SELECT s.id,s.`NAME`,SUM(e.score) 
FROM student s LEFT JOIN scores e on s.id = e.s_id GROUP BY s.id
ORDER BY sum(e.score)DESC

-- 9、查询数学成绩的高分、低分、平均分。 
SELECT MAX(score) ‘数学最高分‘,MIN(score) ‘最低分‘,avg(score) ‘平均分‘
FROM scores e LEFT JOIN course c ON e.c_id = c.id WHERE c.NAME = ‘数学‘;

-- 10、将各科目按照平均分排序。
SELECT avg(score),c.`NAME`
FROM scores e LEFT JOIN course c ON e.c_id = c.id 
GROUP BY c.id ORDER BY avg(score) DESC;

-- 11、查询老师的信息和他所带科目的平均分
SELECT t.id,t.`NAME`,c.`NAME`,AVG(score) score 
FROM teacher t LEFT JOIN course c on t.id = c.t_id
LEFT JOIN scores s ON c.id = s.c_id
GROUP BY t.id,t.`NAME`
ORDER BY score ASC;

-- 12、查询被“张楠”和‘‘老孙’教的课程的高分和平均分。
SELECT t.`NAME` teacher,c.`NAME` project,avg(s.score) ‘平均分‘,MAX(s.score) ‘最高分‘ 
FROM course c LEFT JOIN scores s on c.t_id = s.c_id
LEFT JOIN teacher t ON s.c_id = t.id
WHERE t.`NAME` = ‘张楠‘ OR t.`NAME` =‘老孙‘
GROUP BY c.`NAME`,t.`NAME`;

-- 13、查询每个同学的最好成绩的科目名称
SELECT st.`NAME`,c.`NAME` ‘科目‘,temp.`最高成绩` 
FROM student st LEFT JOIN(
SELECT sc.s_id,MAX(sc.score) ‘最高成绩‘ 
FROM scores sc GROUP BY s_id) temp ON st.id = temp.s_id
LEFT JOIN scores s ON s.score = temp.`最高成绩`
AND s.s_id = temp.s_id
LEFT JOIN course c ON c.id = s.c_id;

-- 14、查询所有学生的课程及分数。** 
SELECT s.name,e.score,c.`NAME` FROM 
student s  LEFT JOIN scores e  on s.id = e.s_id
LEFT JOIN course c on e.c_id = c.id;

-- 15、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
SELECT sc.s_id,st.`NAME`,sc.score
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
LEFT JOIN course c ON sc.s_id = c.id
WHERE c.id = 1 
AND score >= 75;

-- 16、查询平均成绩大于等于70的所有学生的学号、姓名和平均成绩
SELECT st.id ‘学号‘,st.`NAME` ‘姓名‘,avg(sc.score) ‘平均成绩‘
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
GROUP BY s_id
HAVING avg(sc.score) >= 70;

-- 17、查询有不及格课程的同学信息 
SELECT st.id,st.`NAME`,c.`NAME`,sc.score 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
LEFT JOIN course c ON sc.c_id = c.id
WHERE sc.score < 60;

-- 18、求每门课程的学生人数 
SELECT sc.c_id,c.`NAME`,COUNT(sc.s_id) ‘人数‘ 
FROM scores sc LEFT JOIN course c ON sc.c_id = c.id
GROUP BY sc.c_id,c.`NAME`

-- 19、查询每门课程的平均成绩,结果按平均成绩降序排列,
-- 平均成绩相同时,按课程编号升序排列 
SELECT sc.c_id,c.`NAME`,avg(sc.score) ‘平均成绩‘  
FROM scores sc LEFT JOIN course c ON sc.c_id = c.id
GROUP BY sc.c_id,c.`NAME` 
ORDER BY avg(sc.score) DESC,
sc.c_id ASC;

-- 20、查询平均成绩大于等于70分的同学的学生编号和学生姓名和平均 成绩。 
SELECT st.id,st.`NAME`,avg(sc.score) ‘平均成绩‘ 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
GROUP BY sc.s_id
HAVING avg(sc.score) >= 70;

-- 21、查询有一门课程成绩在90分以上的学生信息
SELECT st.id,st.`NAME`,st.age,st.gander,c.`NAME` ‘科目‘,sc.score 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
LEFT JOIN course c ON sc.c_id = c.id
WHERE score > 90;

-- 22、查询出只有三门课程的全部学生的学号和姓名 
SELECT st.id,st.`NAME` 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
LEFT JOIN course c ON c.id = sc.c_id
GROUP BY st.id,st.`NAME`
HAVING COUNT(sc.c_id) = 3;

-- 23、查询有不及格课程的详细信息
SELECT sc.c_id ‘课程编号‘,sc.c_id ‘学号‘, st.`NAME` ‘姓名‘,c.`NAME` ‘科目‘,
sc.score ‘成绩‘,t.`NAME` ‘教师‘
FROM scores sc LEFT JOIN course c ON sc.c_id = c.id
LEFT JOIN student st ON st.id = sc.s_id
LEFT JOIN teacher t ON c.t_id = t.id
WHERE sc.score < 60;

-- 24、检索至少选修四门课程的学生学号 
SELECT st.id ‘学号‘,st.`NAME` ‘姓名‘  
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
GROUP BY st.id,st.`NAME`
HAVING COUNT(sc.c_id) >= 4;

-- 25、查询没有学全所有课程的同学的信息
SELECT * 
FROM student st LEFT JOIN( 
SELECT * FROM scores sc GROUP BY s_id 
HAVING COUNT(c_id) < (SELECT COUNT(*) FROM course))t 
ON st.id = t.s_id

-- 26、查询学全所有课程的同学的信息 
SELECT * 
FROM student s INNER  JOIN (
SELECT s_id FROM scores GROUP BY s_id 
HAVING count( c_id )=( SELECT count(*) FROM course ) ) t   
ON s.id = t.s_id;

-- 27、 查询各学生都选了多少门课 
SELECT st.id,st.`NAME`,COUNT(sc.c_id) ‘数量‘ 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
GROUP BY st.id,st.`NAME`;

-- 28、查询课程名称为”数学”,且分数低于60的学生姓名和数学分数
SELECT st.`NAME`,sc.score ‘成绩‘ 
FROM student st LEFT JOIN scores sc ON st.id = sc.s_id
LEFT JOIN course c ON sc.c_id = c.id
WHERE c.`NAME` = ‘数学‘ AND score < 60;

-- 29、查询学过”张楠”老师授课的同学的信息
SELECT st.id,st.`NAME`,st.gander,st.age,t.`NAME`,c.`NAME` 
FROM course c LEFT JOIN teacher t ON c.t_id = t.id
LEFT JOIN scores sc ON c.id = sc.c_id
LEFT JOIN student st ON sc.s_id = st.id
WHERE t.`NAME` = ‘张楠‘;

-- 30、查询没学过”张楠”老师授课的同学的信息 
SELECT *
FROM student
WHERE id NOT in(
SELECT sc.s_id
FROM course c LEFT JOIN scores sc ON c.id = sc.c_id
LEFT JOIN teacher t ON c.t_id = t.id
WHERE t.`NAME` = ‘张楠‘);

数据库多表查询,请先把我文章的基础知识学会,在钻研难点!!!

原文:https://www.cnblogs.com/wusanshui-a/p/13093397.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!