4.单表-多表查询

表单查询

一.单表查询

数据准备: 直接往MySQL里复制就行

# 创建表
create table employee(
id int not null unique auto_increment,
emp_name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一个部门一个屋子
depart_id int
);


#三个部门:教学,销售,运营
insert into employee(emp_name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龙','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);

多个查询条件共同出现时使用顺序

# 多个查询条件共同出现时使用顺序
"""
select ... from ... where ... group by ... having ... order by ... limit ...  
查询的数据可以用 as 起别名
"""

# 函数 
# 1.concat()函数 -- 将多个字符串连接成一个字符串,相互中间没有字符分隔。
	concat(str1,str2,..)
# 2.concat_ws()函数 -- 将多个字符串连接成一个字符串,相互之间可以指定字符分隔.
	concat_ws(分隔符,str1,str2..)

	

1.where 条件的使用

基本语法:

# 一.where 条件的使用
	功能:对表中的数据进行筛选和过滤
	语法:
    # 1.判断的符号
        > < >= <= = !=( <>不等于 )
    # 2.拼接不同条件的关键字
        and or not
    # 3.查询区间值
        between 小值 and 大值 [小值,大值] 查询两者之间的范围
        not between 小值 and 大值  不在两者之间
    # 4.查询指定数间的值
         in (1,2,3,4,5,6)
         not in
         is
         is not
    #5.模糊查询 like %通配符 _通配符
        like "%b"  匹配以b结尾的任意长度字符串
        like "a%"  匹配以a开头的任意长度字符串
        like "%c%" 匹配字符串中含有c的任意长度字符串
        like "__d" 匹配总长度为3位,而且以d结尾的字符串
        like "e__" 匹配总长度为3位,而且以e开头的字符串
    # 6. 去重 查询字段内种类
        distinct(字段)  

练习where:

# 练习:where
# 1. 查询部门是sale的所有员工姓名:
select emp_name from employee where post='sale';

# 2. 部门是teacher , 收入大于10000的所有数据
select * from employee where post='teacher' and salary > 10000;

# 3. 收入在1万到2万之间的所有员工姓名和收入
select emp_name,salary from employee where salary between 10000 and 20000;

# 4. 收入不在1万到2万之间的所有员工姓名和收入
select emp_name,salary from employee where salary not between 10000 and 20000;

# 5. 查看岗位描述为NULL的员工信息
select * from employee where post_comment is null;

# 6. 查询收入是3000 ,4000 ,5000,8300 所有员工的姓名和收入
select emp_name,salary from employee where salary in (3000,4000,5000,8300); 

# 7. 以on结尾的员工名搜一下
select emp_name from employee where emp_name like '%on';

# 8. 统计员工一年的年薪
select emp_name,salary*12 from employee;

# 9. 查询部门的种类
select distinct(post) from employee;

2.group by 与having用法

# 二. group by 子句  分类,分组  各个部门
"""注意点: 针对于当前表,by谁搜谁"""
    select sex from employee group by sex
    select emp_name from employee group by sex  # error
    # 解决办法  group_concat 按照分组把对应的字段拼接在一起  
    # 查询公司男女员工名字
    select sex,group_concat(emp_name) as name from employee group by sex;

# group_concat语法:
group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc  ] [separator '分隔符'] )

说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,默认逗号分隔。

# 聚合函数 用在group by 中
	# count 统计数量 * 号代表所有 
	select count(*) from employee
	# max 统计最大值
	select max(salary) from employee;
	# min 统计最大值
	select min(salary) from employee;
	# avg 统计平均值
	select avg(salary) from employee;
	# sum 统计总和
	select sum(salary) from employee;

# 三.having 对分类后的数据进行二次过滤[应用在group by这个场景里]

练习group by 和 having:

#练习:group
# 1. 查询部门名以及各部门的平均薪资
select post, avg(salary) as s_avg from employee group by post; 

# 2. 查询部门名以及各部门的最高薪资
select post, max(salary) as s_avg from employee group by post;

# 3. 查询公司内男员工和女员工的个数
select sex, count(sex) from employee group by sex;

# 4. 查询部门名以及部门包含的所有员工名字
select post, group_concat(emp_name) from employee group by post;

#练习:having
# 1.查询各岗位内包含的员工个数大于2的岗位名、岗位内包含员工名字、个数
select post,group_concat(emp_name),count(*) 
from employee 
group by post having count(*) > 2;

# 2.查询各岗位平均薪资小于10000的岗位名、平均工资
select post,avg(salary) as s_avg from employee 
group by post having avg(salary) < 10000;

# 3.查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资
select post,avg(salary) as s_avg from employee 
group by post having avg(salary) > 10000 and avg(salary) < 20000;

3.order by 使用

# 四.order by 排序
    """
    默认升序
    正序 升序 asc
    倒序 降序 desc
    """
#练习:order by
    select * from employee order by age; #(默认升序)
    select * from employee order by age asc; # 升序
    select * from employee order by age desc; # 降序

练习order by;

#练习:order by
# 1. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
select * from employee order by age asc,hire_date desc;

# 2. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列
select post,avg(salary) from employee 
group by post 
having avg(salary) > 10000
order by avg(salary) desc;

4.limit 限制查询的条数

# 五.limit 限制查询的条数
"""
 limit m,n  m代表从第几条搜索数据 , n 代表搜索几条 m=0 代表搜索第一条数据 
 limit n      n 代表搜索几条
 """
# 网页分页浏览
    select * from employee limit 0,10  # 0代表第一条 ,往后搜10条数据
    select * from employee limit 10,10 # 10代表第11条,往后搜10条数据

# limit 数字  代表搜索条数
    select * from employee limit 1;
# 搜索表里面最后一条数据
    select * from employee order by id desc limit 1;
# 搜索表里面最后三条数据
    select * from employee order by id desc limit 3;

# 六.(了解) 可以使用正则表达式 (不推荐使用)
    select * from employee where emp_name regexp ".*n$"; #?号不识别
    select * from employee where emp_name regexp "程咬.*";     

二.多表查询

1.语法

# 1.内联查询(内联接):  inner join ...on.. 至少两表以上做查询,把满足条件的所有数据查询出来(查询的是共同拥有的数据)
    select 字段 from 表1 inner join 表2 on 必要的关联字段 (2张表)
    select 字段 from 表1 inner join 表2 on 必要的关联字段1  inner join 表3 on 必要的关联字段2 ... inner join ... 

    # 语法:
    select * from employee inner join  department on employee.dep_id = department.id ;
    # as 起别名 (推荐)
    select * from employee as e inner join  department as d on e.dep_id = d.id ;
    # as 可以省略
    select * from employee  e inner join  department  d on e.dep_id = d.id ;

    # where 写法默认等价于inner join ..on..也是内联查询
    select * from employee , department  where  employee.dep_id = department.id ;
    select * from employee as e, department as d  where  e.dep_id = d.id ;

# 2.外联查询(外联接)
    # (1) left join ..on.. (左联接) : 以左表为主,右表为辅,完整查询左表所有数据,右表没有的数据补null 
    select * from employee left join   department on employee.dep_id = department.id ;
    # (2) right join ..on.. (右联接): 以右表为主,左表为辅,完整查询右表所有数据,左表没有的数据补null 
    select * from employee right join   department on employee.dep_id = department.id ;

# 3.全联查询(全联接) left join +(union) right join 
    select * from employee left join   department on employee.dep_id = department.id 
    union
    select * from employee right join   department on employee.dep_id = department.id ;

# 4.子查询
"""
子查询 : sql语句的嵌套
	(1) sql语句当中嵌套另外一条sql,用括号()包起来,表达一个整体;
	(2) 一般用在子句的后面 比如from , where ...身后 表达一个条件或者一张表
	(3) 速度快慢 : 单表查询 > 联表查询 > 子查询
"""
# 带EXISTS关键字的子查询
	"""
	exists 关键字,表达数据是否存在,用在子查询里
		如果内层sql 能够查到数据,返回True ,外层sql执行sql语句
		如果内层sql 不能够查到数据,返回False ,外层sql不执行sql语句
	"""
	select * from employee where exists (select * from employee where id = 1);
	
    """
	总结: 
		子查询可以作为临时表,也可以作为where子句的条件,通过()包括sql,表达一个整体;
		一般用在各个子句后面 select .. from ... where ...
	思路:
		可以把临时搜索出来的数据变成临时表,在和其他表做联表,最后做单表查询;
	"""

2.数据准备: MySQL之间粘贴复制

# 1、创建表
# 创建班级表
create table class(
cid int primary key auto_increment,
caption varchar(32) not null
);

# 创建学生表
create table student(
sid int primary key auto_increment,
gender char(1) not null,
class_id int not null,
sname varchar(32) not null,
foreign key(class_id) references class(cid) on delete cascade on update cascade
);

# 创建老师表
create table teacher(
tid int primary key auto_increment,
tname varchar(32) not null
);

# 创建课程表
create table course(
cid int primary key auto_increment,
cname varchar(32) not null,
teacher_id int not null,
foreign key(teacher_id) references teacher(tid) on delete cascade on update cascade
);

# 创建成绩表
create table score(
sid int primary key auto_increment,
student_id int not null,
course_id int not null,
num int not null,
foreign key(student_id) references student(sid) on delete cascade on update cascade,
foreign key(course_id) references course(cid) on delete cascade on update cascade
);


# 2、插入记录
# 班级表插入记录
insert into class values
('1', '三年二班'), 
('2', '三年三班'), 
('3', '一年二班'), 
('4', '二年一班');

# 学生表插入记录
insert into student values
('1', '男', '1', '理解'), 
('2', '女', '1', '钢蛋'), 
('3', '男', '1', '张三'), 
('4', '男', '1', '张一'), 
('5', '女', '1', '张二'), 
('6', '男', '1', '张四'), 
('7', '女', '2', '铁锤'),
('8', '男', '2', '李三'), 
('9', '男', '2', '李一'), 
('10', '女', '2', '李二'), 
('11', '男', '2', '李四'), 
('12', '女', '3', '如花'), 
('13', '男', '3', '刘三'), 
('14', '男', '3', '刘一'), 
('15', '女', '3', '刘二'), 
('16', '男', '3', '刘四');

# 老师表插入记录
insert into teacher values
('1', '张磊'), 
('2', '李平'), 
('3', '刘海燕'), 
('4', '朱云海'), 
('5', '李春秋');

# 课程表插入记录
insert into course values
('1', '生物', '1'), 
('2', '物理', '2'), 
('3', '体育', '3'), 
('4', '美术', '2');

# 成绩表插入记录
insert into score values
('1', '1', '1', '10'), 
('2', '1', '2', '9'), 
('3', '1', '3', '76'),
('5', '1', '4', '66'), 
('6', '2', '1', '8'), 
('8', '2', '3', '68'), 
('9', '2', '4', '99'), 
('10', '3', '1', '77'), 
('11', '3', '2', '66'), 
('12', '3', '3', '87'), 
('13', '3', '4', '99'), 
('14', '4', '1', '79'), 
('15', '4', '2', '11'), 
('16', '4', '3', '67'), 
('17', '4', '4', '100'), 
('18', '5', '1', '79'), 
('19', '5', '2', '11'), 
('20', '5', '3', '67'), 
('21', '5', '4', '100'), 
('22', '6', '1', '9'), 
('23', '6', '2', '100'), 
('24', '6', '3', '67'), 
('25', '6', '4', '100'), 
('26', '7', '1', '9'), 
('27', '7', '2', '100'), 
('28', '7', '3', '67'), 
('29', '7', '4', '88'), 
('30', '8', '1', '9'), 
('31', '8', '2', '100'), 
('32', '8', '3', '67'),
('33', '8', '4', '88'), 
('34', '9', '1', '91'), 
('35', '9', '2', '88'), 
('36', '9', '3', '67'), 
('37', '9', '4', '22'), 
('38', '10', '1', '90'), 
('39', '10', '2', '77'), 
('40', '10', '3', '43'), 
('41', '10', '4', '87'), 
('42', '11', '1', '90'), 
('43', '11', '2', '77'), 
('44', '11', '3', '43'), 
('45', '11', '4', '87'), 
('46', '12', '1', '90'), 
('47', '12', '2', '77'), 
('48', '12', '3', '43'), 
('49', '12', '4', '87'), 
('52', '13', '3', '87');

3.表结构

4.多表查询练习

1、查询所有的课程的名称以及对应的任课老师姓名
-- 思路:课程表和老师表关联起来再查询
-- (1)inner join
select c.cname,t.tname
from teacher as t inner join course as c on t.tid = c.teacher_id;

-- (2)where
select c.cname,t.tname
from teacher as t , course as c where t.tid = c.teacher_id;

2、查询学生表中男女生各有多少人
-- 单表查询:
select gender,count(*) as '人数' from student group by gender;

3、查询物理成绩等于100的学生的姓名
-- 思路: 成绩表,课程表,学生表三表关联
-- (1)inner join
select st.sname,score.num
from 
	student as st inner join score on st.sid = score.student_id 
	inner join course as c on score.course_id = c.cid
where c.cname='物理' and score.num = 100;

--(2)where
select st.sname,score.num
from student as st,score,course as c
where 
	st.sid = score.student_id
	and score.course_id = c.cid
	and c.cname='物理'
	and score.num = 100;

4、查询平均成绩大于八十分的同学的姓名和平均成绩
-- 思路:学生表和成绩表关联,每个学生的平均成绩
-- (1)inner join
select st.sname,avg(score.num) as '平均成绩'
from student as st inner join score on st.sid = score.student_id
group by st.sname having avg(score.num) > 80;

-- (2)where
select st.sname,avg(score.num) as '平均成绩'
from student as st,score
where st.sid = score.student_id
group by st.sname having avg(score.num) > 80;

5、查询所有学生的学号,姓名,选课数,总成绩
-- 思路: 成绩表,学生表关联
-- (1)inner join
select st.sid,st.sname,count(*) as '选课数' ,sum(score.num)as '总成绩'
from 
	student as st inner join score on st.sid = score.student_id 
group by st.sid ;

-- (2)where
select st.sid,st.sname,count(*) as '选课数' ,sum(score.num)as '总成绩'
from student as st,score
where st.sid = score.student_id 
group by st.sid ;

6、 查询姓李老师的个数
-- 单表查询
select count(*) from teacher where tname like '李%';

7、 查询没有报李平老师课的学生姓名
-- 1)先找到报考李平老师课程的学生id - 老师,课程,成绩三表联合
select distinct(sc.student_id)
from 
	score as sc inner join course as co on sc.course_id = co.cid
	inner join teacher as te on te.tid = co.teacher_id
where te.tname = '李平';

-- 2)在学生表中筛选不报李平老师学生id
select sname
from student where sid not in (1的结果);

-- 3)合并
select sname
from student where sid not in (
    select distinct(sc.student_id)
    from 
        score as sc inner join course as co on sc.course_id = co.cid
        inner join teacher as te on te.tid = co.teacher_id
    where te.tname = '李平');

8、 查询物理课程的分数比生物课程的分数高的学生的学号
-- 1.查询上物理课学生学号和分数
select s.student_id,s.num as wuli
from score as s inner join course as c on c.cid = s.course_id
where c.cname = '物理';

-- 2.查询上生物课学生学号和分数
select s.student_id,s.num as shengwu
from score as s inner join course as c on c.cid = s.course_id
where c.cname = '生物';

-- 3.上面查询出的两张表进行关联
select a.student_id
from (1)as a inner jion (2)as b on a.student_id = b.student_id
where wuli > shengwu;

-- 合并最终结果
select a.student_id
from 
    (
        select s.student_id,s.num as wuli
        from score as s inner join course as c on c.cid = s.course_id
        where c.cname = '物理'
    )as a inner join (
    	select s.student_id,s.num as shengwu
        from score as s inner join course as c on c.cid = s.course_id
        where c.cname = '生物'
    )as b on a.student_id = b.student_id
where wuli > shengwu;

9、 查询没有同时选修物理课程和体育课程的学生姓名
-- 思路:先找到同时选修的学生,再排除
-- 1.查询上物理课学生学号
select s.student_id
from score as s inner join course as c on c.cid = s.course_id
where c.cname = '物理';

-- 2.查询上体育课学生学号
select s.student_id
from score as s inner join course as c on c.cid = s.course_id
where c.cname = '体育';

-- 3.上面俩表链表,得到同时选修学生学号
select a.student_id
from 
	(
        select s.student_id
        from score as s inner join course as c on c.cid = s.course_id
        where c.cname = '物理'
    ) as a inner join (
        select s.student_id
        from score as s inner join course as c on c.cid = s.course_id
        where c.cname = '体育'
    )as b on a.student_id = b.student_id; 

-- 4.学生表排除掉同时选修学生学号
select sid,sname
from student
where sid not in (
    select a.student_id
    from 
        (
            select s.student_id
            from score as s inner join course as c on c.cid = s.course_id
            where c.cname = '物理'
        ) as a inner join (
            select s.student_id
            from score as s inner join course as c on c.cid = s.course_id
            where c.cname = '体育'
        )as b on a.student_id = b.student_id
);

10、查询挂科超过两门(包括两门)的学生姓名和班级
-- 方法一:
-- 1.先查询所有挂科的学生学号
select student_id,num from score where num < 60;

-- 2.再找超过两门的学生学号
select 
	a.student_id
from 
	(select student_id,num from score where num < 60) as a
group by 
	a.student_id 
having 
	count(*) >= 2;

-- 3.根据学生表和班级表,查到该学生
select st.sid,st.sname,cl.caption
from student as st inner join class as cl on st.class_id = cl.cid
where st.sid in (
    select a.student_id
    from (select student_id,num from score where num < 60) as a
    group by a.student_id having count(*) >= 2
);

-- 方法二:
select 
	student.sname , class.caption
from 
	score,student,class
where 
	score.student_id = student.sid
	and
	student.class_id = class.cid
	and 
	score.num < 60
group by 
	score.student_id
having 
	count(*) >= 2

11、查询选修了所有课程的学生姓名
select 
	st.sid,st.sname
from 
	score as sc inner join student as st on sc.student_id = st.sid
group by
	st.sid
having 
	count(*) = (select count(*) from course); 
	
12、查询李平老师教的课程的所有成绩记录
-- 1.查询李平老师交什么课
select
	co.cid,co.cname
from 
	teacher as te inner join course as co on te.tid = co.teacher_id
where 
	te.tname = '李平';
	
-- 2.成绩表与上表关联,查询数据
select 
	a.cname,group_concat(sc.num)
from 
	score as sc inner join (
        select
        	co.cid,co.cname
        from 
            teacher as te inner join course as co on te.tid = co.teacher_id
        where 
            te.tname = '李平'
    ) as a on sc.course_id = a.cid
group by
	a.cname;


13、查询全部学生都选修了的课程号和课程名
-- 每个课程选修的数量和学生的数量一样就可以了
select
	co.cid,co.cname
from 
	score as sc inner join course co on sc.course_id = co.cid
group by
	sc.course_id
having
	count(*) = (
    	select count(*) from student
    );


14、查询每门课程被选修的次数
-- 按课程分组查询
select 
	co.cname,count(*) as "被选修的次数"
from 
	score as sc inner join course co on sc.course_id = co.cid
group by
	co.cname;


15、查询只选修了一门课程的学生学号和姓名
-- 按学号分组查询
select
	st.sid,st.sname
from 
	score as sc inner join student as st on sc.student_id = st.sid
group by 
	st.sid
having
	count(*) = 1;


16、查询所有学生考出的成绩并按从高到低排序(成绩去重)
-- 按成绩分组,降序
select
	distinct(num),group_concat(distinct(student_id))
from 
	score
group by
	num
order by
	num desc;


17、查询平均成绩大于85的学生姓名和平均成绩
-- 按学生分组查询
select
	st.sname,avg(num) as '平均成绩'
from 
	score as sc inner join student as st on sc.student_id = st.sid
group by
	st.sname
having	
	avg(num) > 85;


18、查询生物成绩不及格的学生姓名和对应生物分数
-- 成绩,课程,学生三表联表查询
select
	st.sname,co.cname,sc.num
from
	score as sc inner join course as co on sc.course_id = co.cid
	inner join student as st on sc.student_id = st.sid
where 
	co.cname = '生物'
	and
	sc.num < 60;


19、查询在所有选修了李平老师课程的学生中,这些课程(李平老师的课程,不是所有课程)平均成绩最高的学生姓名
-- 1.李平老师教了什么课id  (2,4)
select
	cid
from 
	teacher , course
where 
	teacher.tid = course.teacher_id
	and 
	teacher.tname = "李平"
	
-- 2.在学习了李平老师的课程中,找学生平均成绩最高的学生id
select 
	student_id,avg(num) 
from 
	score
where 
	course_id in (2,4)
group by 
	student_id
order by
	avg(num) desc
limit 1

-- 3.要的是学生姓名,通过在联表student,找sname
 select 
	student_id,student.sname,avg(num) 
from 
	score inner join student on score.student_id = student.sid
where 
	course_id in (2,4)
group by 
	student_id
order by
	avg(num) desc
limit 1

-- 4.综合拼接
select 
	student_id,student.sname,avg(num) 
from 
	score inner join student on score.student_id = student.sid
where 
	course_id in (select
	cid
from 
	teacher , course
where 
	teacher.tid = course.teacher_id
	and 
	teacher.tname = "李平"
	)
group by 
	student_id
order by
	avg(num) desc
limit 1

20、查询每门课程成绩最好的课程id、学生姓名和分数
-- 1.成绩最大值
select 
	course_id,max(num) as max_num
from 
	score
group by
	course_id
	
-- 2.找当前这个分数对应的学生id
select 
	t1.student_id,t2.sname,t3.max_num
from 
	score as t1 inner join student as t2 on t1.student_id = t2.sid
	inner join (1号) as t3 on t1.course_id = t3.course_id
where t1.num = t3.max_num

-- 综合拼接
select 
	t1.student_id,t1.course_id,t2.sname,t3.max_num
from 
	score as t1 inner join student as t2 on t1.student_id = t2.sid
	inner join (select 
	course_id,max(num) as max_num
from 
	score
group by
	course_id) as t3 on t1.course_id = t3.course_id
where t1.num = t3.max_num

21、查询不同课程但成绩相同的课程号、学生号、成绩 
select 
	num,course_id , group_concat(student_id)
from 
	score
where 
	num in (select num from score group by num having count(distinct(course_id)) >= 2)
group by 
	num , course_id;
	
23、查询所有选修了学号为2的同学选修过的一门或者多门课程的同学学号和姓名 
-- 1.查询学号为2的学生,选修的课程id (1,3,4)
select
	course_id
from
	score
where
	student_id = 2
-- 2.学习过1,3,4课程的学生id,学生姓名
select
	distinct(score.student_id),student.sname
from
	score inner join student on score.student_id = student.sid
where
	score.course_id in (1号)
-- 3.拼接
select
	distinct(score.student_id),student.sname
from
	score inner join student on score.student_id = student.sid
where
	score.course_id in (
        select
            course_id
        from
            score
        where
            student_id = 2
    );
24、任课最多的老师中学生单科成绩最高的课程id、学生姓名和分数
-- 1.任课最多的老师课程数最大值
-- 一个老师可以任命最多几个学科  => 2
select 
	count(*)
from 
	course
group by 
	teacher_id
order by
	count(*) desc
limit 1

-- 2.找任课有2个学科的老师id是谁? => 2
select 
	teacher_id
from 
	course
group by 
	teacher_id
having 
	count(*) = 2
	
-- 综合拼接(找到老师id)
select 
	teacher_id
from 
	course
group by 
	teacher_id
having 
	count(*) = (
    select 
        count(*)
    from 
        course
    group by 
        teacher_id
    order by
        count(*) desc
    limit 1
    )

-- 3.通过老师id,找所教的所有课程号cid =>2,4
select 
	cid
from 
	course
where
	teacher_id in(2号)
	
-- 4.按照学科id,找各科成绩最大值(max)
select 
	course_id,max(num) as max_num
from 
	score
where
	course_id in (2,4)
group by 
	course_id

# 综合拼接
select 
	course_id,max(num) as max_num
from 
	score
where
	course_id in (select 
	cid
from 
	course
where
	teacher_id in(select 
	teacher_id
from 
	course
group by 
	teacher_id
having 
	count(*) = (select 
	count(*)
from 
	course
group by 
	teacher_id
order by
	count(*) desc
limit 1)))
group by 
	course_id

-- 5.找对应最高各科成绩的那个学生找出来
select 
	t1.student_id,t2.sname,t3.max_num
from 
	score as t1 inner join student as t2 on t1.student_id = t2.sid
	inner join (4号) as t3 on t3.course_id = t1.course_id
where
	t1.num = t3.max_num
	
# 综合拼接
select 
	t1.student_id,t2.sname,t3.max_num,t1.course_id
from 
	score as t1 inner join student as t2 on t1.student_id = t2.sid
	inner join (select 
	course_id,max(num) as max_num
from 
	score
where
	course_id in (select 
	cid
from 
	course
where
	teacher_id in(select 
	teacher_id
from 
	course
group by 
	teacher_id
having 
	count(*) = (select 
	count(*)
from 
	course
group by 
	teacher_id
order by
	count(*) desc
limit 1)))
group by 
	course_id) as t3 on t3.course_id = t1.course_id
where
	t1.num = t3.max_num
原文地址:https://www.cnblogs.com/jia-shu/p/14263871.html