多表查询
多个表放在一起联合查询。
学生表 student
| id | s_no | s_name |
|---|---|---|
| 1 | fanmao01 | 张三 |
| 2 | fanmao02 | 李四 |
| 3 | fanmao03 | 王大锤 |
| 4 | fanmao04 | 张铁柱 |
成绩表 score
| id | s_no | score |
|---|---|---|
| 1 | fanmao01 | 80 |
| 2 | fanmao02 | 90 |
| 3 | fanmao03 | 100 |
内联 inner join … on
在多表查询的时候,比如上面两个表 ,学生表中的 s_no 跟 成绩表中 s_no 相等。在做两个表查询的时候。
s_no 作为两个表之间的关联纽带。
inner join 表示两个表中 都包含有。

- 查询 学生表,成绩表,参加考试的每位同学的成绩。 ```sql
select xuesheng.id,xuesheng.s_no,s_name,score from chengji INNER JOIN xuesheng — 内联接 ON xuesheng.s_no = chengji.s_no; — 连接的条件
- 因为两个表中 都有id,所有在select 后面使用 student.id , 表示使用student中的id- 因为两个表中都有s_no, student.s_no 表示查看学生表中 s_no;- 因为两个表中只有一个 s_name,s_score , 所以可以只写 s_name, s_score.2. 查询 学生表,成绩表,参加考试的每位同学的成绩, 并按照成绩从大到小排序。```sqlselect xuesheng.id,xuesheng.s_no,s_name,score from chengjiINNER JOIN xuesheng -- 内联接ON xuesheng.s_no = chengji.s_no; -- 连接的条件order by score;
练习
表A:图书信息表

问题(写sQL):
1、查询书名“B”开头且2014年(包含2014年)之后购入的书籍清单,显示字段 barcode,name, amount,date
select a.barcode,name,amount,date from ainner join bon a.barcode = b.barcode -- 表关联where name like "B%" and year(date)>=2014; -- 条件
2、统计每部书的总数量,显示字段: barcode,name,总量
select a.barcode , name , sum(amount) 总量 from bINNER JOIN a on a.Barcode = b.Barcode -- 把表关联group by a.barcode,name; -- 因为 barcode 对应 name 分组的时候用两个字段分组;
3、统计购入次数大于1次的书,显示字段: barcode,name,购入次数
select a.barcode, name, COUNT(*) as 购入次数 from aINNER JOIN b on a.Barcode = b.BarcodeGROUP BY b.Barcode, name HAVING COUNT(*)>1;
4、统计每本书的销量,按照销量大小降序排序,显示 barcode, name, 销量;
-- 统计每本书的销量,按照销量大小降序排序,显示 barcode, name, 销量;SELECT b.barcode,NAME,SUM(amount)FROM aINNER JOIN b on a.barcode=b.barcode -- 表关联GROUP BY b.barcode,NAME -- 分组ORDER BY SUM(amount) DESC ; -- 排序
5、统计销量最高的图书,显示 barcode, name, 销量;
-- 1. 找到最大销量值。-- 1.1 先找每个书的销量select barcode,sum(amount) from b GROUP BY barcode;-- 1.2 排序select sum(amount) from b GROUP BY barcode order by sum(amount) desc limit 1;-- 2 barcode, name, 销量select a.barcode,name,sum(amount) as 销量 from aINNER JOIN b ON a.Barcode = b.BarcodeGROUP BY a.barcode,nameHAVING 销量=100; -- 100 是上一句查询出来的结果-- 3 合并语句select a.barcode,name,sum(amount) as 销量 from aINNER JOIN b ON a.Barcode = b.BarcodeGROUP BY a.barcode,name-- 将100 替换为具体的查询语句HAVING 销量=(select sum(amount) from b GROUP BY barcode order by sum(amount) desc limit 1);
左联 left join … on
左联和内联的区别:
内联取两个表共有的。
左联是以 左表 为主,跟另外一张表关联,如果另外一张表中,没有对应的值,就显示为Null。


学生表和成绩表
关系: xuesheng.s_no = chengji.s_no
查询所有同学的考试成绩。显示 学号(s_no),姓名(s_name),成绩(score);
因为要查看所有的学生,以学生表 为主。 xuesheng 表作为左表。
select xuesheng.s_no,s_name,score from xuesheng -- xuesheng 主表left join chengjion xuesheng.s_no = chengji.s_no;

右连right join
跟左连接原理一样,以右表为主。
市场上 90% 的开发人员习惯使用左连。
举个例子
SELECT * from xueshengRIGHT JOIN chengjiON xuesheng.s_no = chengji.s_no;
right join 后面跟 chengji 表,所以是以chengji表为主表, chengji表中有个 fanmao06的学号,但是学生表中没有这个学号,查询出来的结果就会为空。
查询 chengji 表与 kecheng 表, chengji为主表。使用右连。
select chengji.c_no,c_name,score from kechengright join chengjion chengji.c_no = kecheng.c_no;
union 连接
Mysql数据库中不支持外连接,使用 union 连接查询的结果。
SELECT count(*) from studentsWHERE sex = "man"UNIONSELECT count(*) from studentsWHERE sex = "woman"
在两个select语句之间 使用 union 可以将两个结果放到一起;
查询students表中,显示语文分数最高的同学,数学分数最高的同学;
分别找出语文最高分,数学最高分,然后使用union 合并到一起;
-- 语文最高分select max(score) from students where course = "语文";select max(score) from students where course = "数学";-- 使用 union 连接结果SELECT * FROM students WHERE score = (select max(score) from students where course = "语文") AND course = "语文"UNIONSELECT * FROM students WHERE score = (select max(score) from students where course = "数学") AND course = "数学"UNIONSELECT * FROM students WHERE score = (select max(score) from students where course = "英语") AND course = "英语"
练习

- 统计每个同学的参与考试成绩, 显示学号,姓名,科目,成绩
分析: 需要使用到 3张表
select xuesheng.s_no,s_name,c_name,score from xueshenginner join chengji on xuesheng.s_no = chengji.s_noinner join kecheng on kecheng.c_no = chengji.c_no -- 三个表关联
- 查询每个同学考试的成绩, 显示 学号s_no, 姓名 s_name, 科目 c_name ,成绩 score ,老师名字t_name;
select xuesheng.s_no, s_name,c_name,score,t_name from chengjiINNER JOIN xuesheng on xuesheng.s_no = chengji.s_noINNER JOIN kecheng on kecheng.c_no = chengji.c_noINNER JOIN laoshi on laoshi.t_no = kecheng.t_no;
作业

- 统计参加的每门课程的人数, 显示 课程名c_name,数量。 ```sql select c_name, count(*) from chengji INNER JOIN kecheng on chengji.c_no = kecheng.c_no GROUP BY c_name;
2. 统计平均分最高的科目```sql-- 1. 找到最高的值select avg(score) from chengji GROUP BY c_no ORDER BY avg(score) desc limit 1 ;-- 2. 根据值找到对应的科目 -- 97.5-- 找到平均分为97.5 的科目SELECT c_no, avg(score) from chengjiGROUP BY c_noHAVING avg(score) = 97.5; -- c4 ,c3-- 3 找到对应的科目SELECT c_no, avg(score) as 平均分 from chengjiGROUP BY c_noHAVING avg(score) = (select avg(score) from chengji GROUP BY c_no ORDER BY avg(score) desc limit 1); -- 临时表-- 合并select c_name, 平均分 from kechengINNER JOIN-- 上面的结果作为临时表( SELECT c_no, avg(score) as 平均分 from chengjiGROUP BY c_noHAVING avg(score) = (select avg(score) from chengji GROUP BY c_no ORDER BY avg(score) desc limit 1) ) as tmpon kecheng.c_no = tmp.c_no;
第二种写法
-- 1. 找到最高的值select avg(score) from chengji GROUP BY c_no ORDER BY avg(score) desc limit 1 ;-- 2 找到等于最高分的科目SELECT c_name,AVG(score) from kechengINNER JOIN chengji on kecheng.c_no = chengji.c_no-- 关联表之后 再做过滤GROUP BY chengji.c_no,c_nameHAVING AVG(score) = ( -- 平均分最高select avg(score) from chengji GROUP BY c_no ORDER BY avg(score) desc limit 1)
统计每个学生的总分
SELECT s_name, sum(score) FROM xueshengLEFT JOIN chengji on xuesheng.s_no = chengji.s_noGROUP BY xuesheng.s_no, s_name
统计总分最高的学生姓名,总分。 ```sql — 最高分 SELECT sum(score) FROM xuesheng LEFT JOIN chengji on xuesheng.s_no = chengji.s_no GROUP BY xuesheng.s_no, s_name ORDER BY SUM(score) DESC LIMIT 1;
— 找人 SELECT s_name, sum(score) FROM xuesheng LEFT JOIN chengji on xuesheng.s_no = chengji.s_no GROUP BY xuesheng.s_no, s_name HAVING SUM(score) = ( SELECT sum(score) FROM xuesheng LEFT JOIN chengji on xuesheng.s_no = chengji.s_no GROUP BY xuesheng.s_no, s_name ORDER BY SUM(score) DESC LIMIT 1 );
5. 统计参加考试的科目中 每门课成绩 都大于60分的学生 姓名,科目,成绩。```sql-- 最小分 大于60 的学号SELECT s_no from chengjiGROUP BY s_noHAVING min(score) > 60;SELECT s_name,c_name,score from xueshengINNER JOIN chengji on xuesheng.s_no = chengji.s_noINNER JOIN kecheng on chengji.c_no = kecheng.c_nowhere xuesheng.s_no in (SELECT s_no from chengjiGROUP BY s_noHAVING min(score) > 60)
