[MySQL]-05MySQL-SQL语句-多表查询

第1章 多表查询

1.多表查询类型

导入数据

source /root/school.sql

1.1 笛卡尔乘积

select * from teacher,course;
或者: 
select * from teacher join course;

拿着 teacher每行数据和course逐行进行组合,显示
两层for循环的实现逻辑。Simple-Nextloop (嵌套循环方式)
得出的结果,会有部分数据是无意义的。

1.2 内连接 join 取交集

mysql> select * from teacher join course on teacher.tno=course.tno ;
+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux  | 101 |
| 102 | hesw   | 1002 | python | 102 |
| 103 | oldguo | 1003 | mysql  | 103 |
+-----+--------+------+--------+-----+
3 rows in set (0.00 sec)

mysql> select * from teacher,course where teacher.tno=course.tno;
+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux  | 101 |
| 102 | hesw   | 1002 | python | 102 |
| 103 | oldguo | 1003 | mysql  | 103 |
+-----+--------+------+--------+-----+
3 rows in set (0.00 sec)

1.3 外连接 left join , right join

mysql> select * from teacher left join course on teacher.tno=course.tno; 
+-----+--------+------+--------+------+
| tno | tname  | cno  | cname  | tno  |
+-----+--------+------+--------+------+
| 101 | oldboy | 1001 | linux  |  101 |
| 102 | hesw   | 1002 | python |  102 |
| 103 | oldguo | 1003 | mysql  |  103 |
| 104 | oldx   | NULL | NULL   | NULL |
| 105 | oldw   | NULL | NULL   | NULL |
+-----+--------+------+--------+------+
5 rows in set (0.00 sec)

mysql> select * from teacher right join course on teacher.tno=course.tno;    
+------+--------+------+--------+-----+
| tno  | tname  | cno  | cname  | tno |
+------+--------+------+--------+-----+
|  101 | oldboy | 1001 | linux  | 101 |
|  102 | hesw   | 1002 | python | 102 |
|  103 | oldguo | 1003 | mysql  | 103 |
| NULL | NULL   | 1004 | k8s    | 108 |
+------+--------+------+--------+-----+
4 rows in set (0.00 sec)

2.多表连接语法

2.1 a表 和 b表 有直接的关联关系

select a.x,b.y  from a  join b on a.z=b.z  where  group by  having order by limit;

select a.x,b.y  	#查找的内容
from a 
join b 				    #a关联b
on a.z=b.z  		  #关联条件
where  				    #其他条件
group by  			  #分组依据
having 				    #分组后判断
order by 			    #排序规则
limit;			    	#显示条目

2.2 a表 和 b表 没有直接的关联关系

假如:a和c 有关,b和c有关

a join c on a.i = c.j join b on c.x=b.y

a join c 
on a.i = c.j 
join b 
on c.x=b.y

2.3 套路

1.根据题意将所有涉及到的表找出来 a b 
2.找到a和b直接或者间接的关联条件 
3.用join on 语句把所有表连接到一起
4.罗列其他查询条件

================================
1.需要哪些表?

2.关联条件是什么

3.多张表关联在一起
select * 
from 
join 
on

4.过滤条件

3.大量练习

3.1 导入数据

source /root/school.sql

关系图:

3.2 每位老师所教课程名称

select 
teacher.tname,course.cname
from teacher 
join course
on teacher.tno=course.tno;

3.3 统计每个学员的姓名及其学习课程的门数

select student.sname'学生姓名',COUNT(*)'学习门数'
from student
join sc
on student.sno=sc.sno
GROUP BY student.sno;

3.4 统计每个学员姓名及其学习课程的门数和课程名列表

关系图:

student ----> sc  ----> course

语句:

select sname,count(*),group_concat(cname) 
from student
join sc
on student.sno = sc.sno
join course 
on sc.cno = course.cno
group by sname;

更严谨的写法:

select CONCAT(student.sname,"_",student.sno),COUNT(*),GROUP_CONCAT(course.cname)
from student 
join sc
on student.sno=sc.sno
join course 
on sc.cno=course.cno
group by student.sno;

3.5 每位老师姓名及其教的学生数量和学生名列表

关系图:

student ----> sc  ----> course ---> teacher

语句:

select CONCAT(teacher.tname,"_",teacher.tno),COUNT(*),GROUP_CONCAT(student.sname)
from teacher 
join course
on teacher.tno=course.tno
join sc
on course.cno=sc.cno 
join student
on sc.sno=student.sno
group by teacher.tno

3.6 每位老师教所教课程的平均分

select CONCAT(teacher.tname,"_",teacher.tno,"_",course.cno),AVG(sc.score)
from teacher 
join course
on teacher.tno=course.tno
join sc
on course.cno=sc.cno 
group by teacher.tno , course.cno

3.7 查找学习了hesw但没学习oldguo课程的学生名

case用法:

select case when 1=1 then "true" end

USE mysql;
SELECT 
case
WHEN USER='root' THEN HOST END,
WHEN USER !='root' THEN 2 END
FROM mysql.user;

USE mysql;
SELECT 
CASE
WHEN USER='root' THEN HOST
WHEN USER !='root' THEN 2 END
FROM mysql.user;

方法1:

select a.sname from 
a
left join
b
on a.sname=b.sname
where b.sname is null;

select a.sname from 
(select student.sname
from teacher 
join course
on teacher.tno=course.tno
join sc
on course.cno=sc.cno 
join student
on sc.sno=student.sno
where teacher.tname = 'hesw') as a
left join 
(select student.sname  
from teacher 
join course
on teacher.tno=course.tno
join sc
on course.cno=sc.cno 
join student
on sc.sno=student.sno
where teacher.tname = 'oldguo') as b
on a.sname=b.sname
where b.sname is null 

方法2:

SELECT student.`sname`,GROUP_CONCAT(teacher.`tname`)
FROM course
JOIN sc 
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno
JOIN teacher
ON course.tno=teacher.tno
GROUP BY student.sname
HAVING GROUP_CONCAT(teacher.`tname`) LIKE '%hesw%' AND GROUP_CONCAT(teacher.`tname`) NOT LIKE '%oldguo%';

3.8 查询出只选修了一门课程的全部学生的学号和姓名

SELECT student.sname,student.sno,COUNT(sc.cno)
FROM sc
JOIN student
ON sc.sno=student.sno
GROUP BY sc.sno
HAVING COUNT(sc.cno)=1;

3.9 查询各科成绩最高和最低的分:以如下形式显示:课程名称,最高分,最低分

SELECT course.cname'课程名称',MAX(sc.`score`)'最高分',MIN(sc.`score`)'最低分'
FROM sc
JOIN course
ON sc.cno=course.cno
GROUP BY course.cname;

3.10 查询平均成绩大于85的所有学生的学号、姓名和平均成绩

select sc.sno,student.sname,AVG(sc.score) 
from sc
join student
on sc.sno=student.sno
group by sc.sno
having AVG(sc.score)>85;

3.11 统计每门课程:优秀(85分以上),良好(70-85),一般(60-70),不及格(小于60)的学生列表

select 
course.cname , 
GROUP_CONCAT(case when sc.score>=85 then  student.sname end),
GROUP_CONCAT(case when sc.score>=70 and sc.score<85 then  student.sname end),
GROUP_CONCAT(case when sc.score>=60 and sc.score<70 then  student.sname end),
GROUP_CONCAT(case when sc.score<60 then  student.sname end)
from course
join sc 
on course.cno=sc.cno
join student
on sc.sno=student.sno 
group by course.cno

SELECT course.cname,
GROUP_CONCAT(CASE WHEN sc.score>=85 THEN CONCAT(student.sname,":",sc.score) END)'优秀',
GROUP_CONCAT(CASE WHEN sc.score>=75 AND sc.`score`<85 THEN CONCAT(student.sname,":",sc.score) END)'良好',
GROUP_CONCAT(CASE WHEN sc.score>=60 AND sc.`score`<75 THEN CONCAT(student.sname,":",sc.score) END)'一般'
FROM course
JOIN sc 
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno
GROUP BY course.cname;

3.12 表别名使用

select 
a.cname , 
GROUP_CONCAT(case when b.score>=85 then  c.sname end),
GROUP_CONCAT(case when b.score>=70 and b.score<85 then  c.sname end),
GROUP_CONCAT(case when b.score>=60 and b.score<70 then  c.sname end),
GROUP_CONCAT(case when b.score<60 then  c.sname end)
from course as a
join sc as b 
on a.cno=b.cno
join student as c
on b.sno=c.sno 
group by a.cno 

3.13 列别名

select 
a.cname as "课程名称" , 
GROUP_CONCAT(case when b.score>=85 then  c.sname end) as "优秀学员",
GROUP_CONCAT(case when b.score>=70 and b.score<85 then  c.sname end) as "良好学员",
GROUP_CONCAT(case when b.score>=60 and b.score<70 then  c.sname end) as "一般学员",
GROUP_CONCAT(case when b.score<60 then  c.sname end) as "不及格学员"
from course as a
join sc as b 
on a.cno=b.cno
join student as c
on b.sno=c.sno 
group by a.cno 

第2章 元数据获取

1.常用show语句

help show;
show databases;          			    # 查询所有库名
show tables;             			    # 查询当前库的所有表名  
show tables from world;  			    # 查询world库下的所有表名
show create database world;     	# 查询world建库语句
show create table city;         	# 当前库下的city表建表语句
show create table world.city;   	# world库下的建表语句   
show privileges;                	# 数据库中所有权限
show engines;                   	# 数据库中支持的存储引擎
show grants for root@'localhost'	# 查询某个用户权限
show charset;                     # 查询数据库字符集支持
show collation;                   # 查询所有校对规则的支持
show variables like '%trx%'       # 查询数据库参数 
show status like 'com_%'          # 查询数据库的状态
show processlist;                 # 查询所有会话信息
show engine innodb status         # 查询innodb引擎相关的状态
show binary logs                  # 查询二进制日志文件信息
show binlog events in 'xxx'       # 查看二进制日志事件
show master status ;              # 当前正在使用的二进制日志信息
show slave statusG               # 查看主从状态相关信息
show slave hosts;                 # 查看从库主机信息
原文地址:https://www.cnblogs.com/alaska/p/14961698.html