多表连接查询

多表连接查询

-- 1. 预备工作

CREATE DATABASE school CHARSET utf8;
USE school
CREATE TABLE student(
sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(20) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED  NOT NULL COMMENT '年龄',
ssex  ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性别'
)ENGINE=INNODB CHARSET=utf8;

CREATE TABLE course(
cno INT NOT NULL PRIMARY KEY COMMENT '课程编号',
cname VARCHAR(20) NOT NULL COMMENT '课程名字',
tno INT NOT NULL  COMMENT '教师编号'
)ENGINE=INNODB CHARSET utf8;

CREATE TABLE sc (
sno INT NOT NULL COMMENT '学号',
cno INT NOT NULL COMMENT '课程编号',
score INT  NOT NULL DEFAULT 0 COMMENT '成绩'
)ENGINE=INNODB CHARSET=utf8;

CREATE TABLE teacher(
tno INT NOT NULL PRIMARY KEY COMMENT '教师编号',
tname VARCHAR(20) NOT NULL COMMENT '教师名字'
)ENGINE=INNODB CHARSET utf8;

INSERT INTO student(sno,sname,sage,ssex)
VALUES 
(1,'zhang3',18,'m'),
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f'),
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f'),
(8,'oldboy',20,'m'),
(9,'oldgirl',20,'f'),
(10,'oldp',25,'m');

INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo')
(104,'alex');

INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103)
(1004,'go',105);

INSERT INTO sc(sno,cno,score)
VALUES
(1,1001,80),
(1,1002,59),
(2,1002,90),
(2,1003,100),
(3,1001,99),
(3,1003,40),
(4,1001,79),
(4,1002,61),
(4,1003,99),
(5,1003,40),
(6,1001,89),
(6,1003,77),
(7,1001,67),
(7,1003,82),
(8,1001,70),
(9,1003,80),
(10,1003,96);

-- 2. 多表连接的类型

-- 笛卡尔乘积

mysql> select * from teacher , course;

+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux  | 101 |
| 102 | hesw   | 1001 | linux  | 101 |
| 103 | oldguo | 1001 | linux  | 101 |
| 104 | alex   | 1001 | linux  | 101 |
| 101 | oldboy | 1002 | python | 102 |
| 102 | hesw   | 1002 | python | 102 |
| 103 | oldguo | 1002 | python | 102 |
| 104 | alex   | 1002 | python | 102 |
| 101 | oldboy | 1003 | mysql  | 103 |
| 102 | hesw   | 1003 | mysql  | 103 |
| 103 | oldguo | 1003 | mysql  | 103 |
| 104 | alex   | 1003 | mysql  | 103 |
| 101 | oldboy | 1004 | go     | 105 |
| 102 | hesw   | 1004 | go     | 105 |
| 103 | oldguo | 1004 | go     | 105 |
| 104 | alex   | 1004 | go     | 105 |
+-----+--------+------+--------+-----+

-- 内连接 (取交集)

SQL92: 
mysql> select *from teacher , course where teacher.tno=course.tno;
SQL99: 
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 |
+-----+--------+------+--------+-----+

-- 外连接 (左、右)

mysql> 
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 | alex   | NULL | NULL   | NULL |
+-----+--------+------+--------+------+
4 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 | go     | 105 |
+------+--------+------+--------+-----+

-- 3. 多表连接语法格式

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

select xxx 
from a join b 
on a.x=b.y 
join c 
on b.z=c.zz

核心思路: 
    1.找到所有相关表 
    2.找到所有表之间的关联关系
    3.罗列其他的查询条件

--3. 多表连接例子:

---  统计学员zhang3,学习了几门课
SELECT student.sname,COUNT(*) 
FROM student  JOIN sc 
ON student.sno =sc.sno
WHERE student.sname='zhang3';

--- 所有学员学习的课程门数
SELECT student.sname,COUNT(*) 
FROM student  JOIN sc 
ON student.sno =sc.sno
GROUP BY student.sname;

--- 查询zhang3,学习的课程名称有哪些?
SELECT student.sname,GROUP_CONCAT(course.cname)
FROM student
JOIN sc
ON student.sno=sc.sno 
JOIN course
ON sc.cno=course.cno
WHERE student.sname = 'zhang3'
GROUP BY student.sname;

--- 查询oldguo所教课程的平均分数

SELECT teacher.tname ,AVG(sc.score) FROM 
teacher  
JOIN course 
ON teacher.tno=course.tno
JOIN sc 
ON course.cno=sc.cno
WHERE teacher.tname='oldguo'
GROUP BY teacher.tname;

--- 每位老师所教课程的平均分,并按平均分排序

SELECT teacher.tname ,AVG(sc.score) FROM 
teacher  
JOIN course 
ON teacher.tno=course.tno
JOIN sc 
ON course.cno=sc.cno
GROUP BY teacher.tname
ORDER BY AVG(sc.score);

--- 查询oldguo所教的不及格的学生姓名

SELECT teacher.tname,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 
WHERE teacher.tname='oldguo'  AND sc.score<60
GROUP BY teacher.tname ;

--- 查询所有老师所教学生不及格的信息

SELECT teacher.tname,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 
WHERE  sc.score<60
GROUP BY teacher.tname ;

别名的使用

-- 表别名

SELECT a.tname,GROUP_CONCAT(d.sname) FROM 
teacher AS a 
JOIN course AS  b 
ON a.tno=b.tno 
JOIN sc AS c 
ON b.cno=c.cno 
JOIN student  AS d 
ON c.sno=d.sno 
WHERE  c.score<60
GROUP BY a.tname ;

-- 列别名

SELECT a.tname AS aa  ,GROUP_CONCAT(d.sname) AS bb FROM 
teacher AS a 
JOIN course AS  b 
ON a.tno=b.tno 
JOIN sc AS c 
ON b.cno=c.cno 
JOIN student  AS d 
ON c.sno=d.sno 
WHERE  c.score<60
GROUP BY a.tname ;

SELECT teacher.tname AS '老师名' ,AVG(sc.score) AS '平均分' FROM 
teacher  
JOIN course 
ON teacher.tno=course.tno
JOIN sc 
ON course.cno=sc.cno
GROUP BY teacher.tname
ORDER BY 平均分;

你可能感兴趣的:(多表连接查询)