-- 老师表
CREATE TABLE `teacher` (
`tno` varchar(20) NOT NULL,
`tname` varchar(20) NOT NULL,
`tsex` varchar(20) NOT NULL,
`tbirthday` datetime DEFAULT NULL,
`prof` varchar(20) DEFAULT NULL,
`depart` varchar(20) NOT NULL,
PRIMARY KEY (`tno`)
)
INSERT INTO `teacher` VALUES ('804','李诚','男','1958-12-02 00:00:00','副教授','计算机系')
,('825','王萍','女','1972-05-05 00:00:00','助教','计算机系')
,('831','刘冰','女','1977-08-14 00:00:00','助教','电子工程系')
,('856','张旭','男','1969-03-12 00:00:00','讲师','电子工程系');
-- 课程表
CREATE TABLE `course` (
`cno` varchar(20) NOT NULL,
`cname` varchar(20) NOT NULL,
`tno` varchar(20) NOT NULL,
PRIMARY KEY (`cno`)
)
INSERT INTO `course` VALUES
('3-105','计算机导论','825'),('3-245','操作系统','804')
,('6-166','数字电路','856'),('9-888','高等数学','831');
-- 学生表
CREATE TABLE `student` (
`sno` varchar(20) NOT NULL,
`sname` varchar(20) NOT NULL,
`ssex` varchar(20) NOT NULL,
`sbirthday` datetime DEFAULT NULL,
`class` varchar(20) DEFAULT NULL,
PRIMARY KEY (`sno`)
)
INSERT INTO `student` VALUES ('101','曾华','男','1977-09-01 00:00:00','95033')
,('102','匡明','男','1975-10-02 00:00:00','95031')
,('103','王丽','女','1976-01-23 00:00:00','95033')
,('104','李军','男','1975-02-10 00:00:00','95033')
,('105','王芳','女','1974-06-03 00:00:00','95031')
,('106','陆君','男','1974-06-03 00:00:00','95031')
,('107','王尼玛','男','1976-02-20 00:00:00','95033')
,('108','张全蛋','男','1975-02-10 00:00:00','95031')
,('109','赵铁柱','男','1974-06-03 00:00:00','95031')
,('110','赵英俊','女','1978-05-01 00:00:00','95033')
,('111','王二妮','女','1978-04-30 00:00:00','95033')
,('112','赵四','男','1977-03-23 00:00:00','95031')
,('113','李乔','女','1976-12-30 00:00:00','95031')
,('114','孙宾','女','1979-02-28 00:00:00','95033')
,('115','李家村','男','1978-09-13 00:00:00','95031');
--成绩表
CREATE TABLE `score` (
`sno` varchar(20) NOT NULL,
`cno` varchar(20) NOT NULL,
`degree` decimal(10,0) DEFAULT NULL
)
INSERT INTO `score` VALUES ('101','3-105',91),('103','3-105',74),('105','3-105',81),('107','3-105',79),('109','3-105',76),('110','3-105',59)
,('111','3-105',95),('113','3-105',94),('115','3-105',77),('101','3-245',71),('102','3-245',93),('103','3-245',78),('106','3-245',68),('110','3-245',92),('111','3-245',89),('114','3-245',65),('115','3-245',93),('101','6-166',77)
,('102','6-166',78),('105','6-166',94),('106','6-166',94),('107','6-166',61),('110','6-166',68),('111','6-166',62),('113','6-166',86),('114','6-166',53)
,('115','6-166',60),('101','9-888',76),('103','9-888',66),('105','9-888',94),('106','9-888',59),('107','9-888',74),('108','9-888',56),('109','9-888',76)
,('112','9-888',62),('113','9-888',50),('114','9-888',77),('115','9-888',69);
select s.sno,s.sname,s.ssex,s.sbirthday,s.class from student s
inner join(
select sno
,max(case when cname='操作系统' then degree end)os_degree
,max(case when cname='计算机导论' then degree end)compute_degree
from score sc inner join course c on c.cno=sc.cno
group by sno
)b on s.sno=b.sno;
select s.sno,s.sname,cast(avg(sc.degree) as decimal(10,1))avg_degree
from student s
inner join score sc on s.sno=sc.sno
group by s.sno,s.sname
having avg(sc.degree)>=60
order by 3 desc;
select s.sno,s.sname,count(*)course_cnt,sum(sc.degree)avg_degree
from student s
left join score sc on s.sno=sc.sno
group by s.sno,s.sname
order by 3 desc;
select s.sno,s.sname
from student s
where s.sno in(
select sno from score group by sno
);
select s.sno,s.sname
from student s
left join score sc on s.sno=sc.sno
where sc.degree is not null
group by s.sno,s.sname;
select count(*)stu_cnt from student where sname like '王%'
select s.sno,s.sname,s.ssex,s.sbirthday,s.class
from teacher t
inner join course c on c.tno=t.tno
inner join score sc on c.cno=sc.cno
inner join student s on sc.sno=s.sno
where t.tname='王萍'
order by s.sno;
select * from student
where sno in(
select sno from score sc
group by sno
having count(*)<(select count(*) from course)
);
-- 将所有人学习的课程与李同学学习的课程号一一关联。然后统计学习数量。如果数据和李同学一样那就表示一样
select * from (
select b.sno,b.sname,ssex
,count(distinct b.cno )c_cnt
from (
select s.sno,sc.cno,s.sname from student s
inner join score sc on s.sno=sc.sno
where s.sname='李巧'
)a left join(
select s.sno,sc.cno,s.sname,s.ssex from student s
inner join score sc on s.sno=sc.sno
-- where s.sname!='李巧'
)b on a.cno=b.cno
group by b.sno,b.sname,ssex
)a
where sname!='李巧' and c_cnt=(
select count(distinct sc.cno) from student s
inner join score sc on s.sno=sc.sno
where s.sname='李巧'
);
--- 方法二
-- - 假设所有人都学了和李巧一样的课程(使用笛卡尔积),然后看大家也有没有没有分数的课程,没有的话就表示一样
select
a.sno,a.sname,a.ssex,a.sbirthday
-- ,count(case when b.degree is null then 1 end)cnt
from (
select s.sno,s.sname,s.ssex,s.sbirthday,a.cno
from (
select sc.cno
from student s
inner join score sc on s.sno=sc.sno
where s.sname='李巧'
)a,student s
)a left join score b on a.cno=b.cno and a.sno=b.sno
where a.sname!='李巧'
group by a.sno,a.sname,a.ssex,a.sbirthday
having count(case when b.degree is null then 1 end)=0
-- 至少有一门,那就是所有学生的有分数课程no与王尼玛的课程no关联有值就表示有
select b.sno,b.sname,count(*)cnt from (
select cno from student s
inner join score sc on s.sno=sc.sno
where s.sname='王尼玛'
)a inner join (
select s.sno,s.sname,cno from student s
inner join score sc on s.sno=sc.sno
where s.sname!='王尼玛'
)b on a.cno=b.cno
group by b.sno,b.sname
--反向查询、或者也可以假设所有人都学了张老师的课。然后在查谁没有这门课的成绩
select * from student s
where s.sno not in(
select sno
from score sc
where sc.cno in(
select c.cno from course c
inner join teacher t on c.tno=t.tno and t.tname='张旭'
)
)
select s.sno,s.sname
,cast(count(distinct case when sc.degree<60 then sc.cno end) as decimal(10,1))not_pass_cnt
,cast(avg(sc.degree) as decimal(10,1))acg_degree
from student s
left join score sc on s.sno=sc.sno
group by s.sno,s.sname
having not_pass_cnt>=1
select sno,sname,ssex,year(now())-year(sbirthday)sage from student
select avg(sc.degree)min_degree
from student s inner join score sc on sc.sno=s.sno
where year(sbirthday)=1974
select * from (
select s.sno,s.sname,c.cname,sc.degree
,rank() over(partition by s.sno,s.sname order by sc.degree)orderid
from course c
inner join score sc on c.cno=sc.cno
inner join student s on sc.sno=s.sno
)a
where orderid=1;
--不使用开窗函数
select a.sno,a.sname,c.cname,sc.degree
from (
select s.sno,s.sname
,min(sc.degree)min_degree
from score sc
inner join student s on sc.sno=s.sno
group by s.sno,s.sname
)a inner join score sc on a.min_degree=sc.degree
inner join course c on c.cno=sc.cno
select c.cname,t.tname,sc.degree
,rank() over (partition by c.cno order by sc.degree desc)rank_id
from course c
inner join score sc on c.cno=sc.cno
inner join teacher t on t.tno=c.tno;
select * from student where month(sbirthday)=month(now())
--将所有学生的出生年份换算到今年然后进行比较
select * from student
where date_add(sbirthday,interval (year(now())-year(sbirthday)) year)<=date_add(now(),interval 1 month)
and date_add(sbirthday,interval (year(now())-year(sbirthday)) year)>=curdate()
select s.sno,s.sname
,count(distinct sc.cno)course_cnt,sum(sc.degree)total_degree
from student s
left join score sc on s.sno=sc.sno
group by s.sno,s.sname
order by 1;
use school;
select c.cno,cname
,count(distinct sc.sno)stu_cnt
,max(sc.degree)max_degree
,min(sc.degree)min_degree
,avg(sc.degree)avg_degree
,count(distinct case when sc.degree>=60 then sc.sno end)*100/count(distinct sc.sno) pass_ratio
,count(distinct case when sc.degree>=80 then sc.sno end)*100/count(distinct sc.sno) excellent_ratio
from course c
left join score sc on c.cno=sc.cno
group by c.cno,cname
order by 3 desc
select c.cname,c.cno,count(*)students
,cast(sum(case when degree<=100 and degree>=85 then 1 else 0 end)*100/count(*) as decimal(10,2)) '[100-85]'
,cast(sum(case when degree<85 and degree>=70 then 1 else 0 end)*100/count(*) as decimal(10,2)) '[85-70]'
,cast(sum(case when degree<70 and degree>=60 then 1 else 0 end)*100/count(*) as decimal(10,2)) '[70-60]'
,cast(sum(case when degree<60 then 1 else 0 end)*100/count(*) as decimal(10,2)) '[60-0]'
from course c
inner join score sc on c.cno=sc.cno
group by c.cname,c.cno
select * from (
select c.cname,s.sno,s.sname,sc.degree
,row_number() over(partition by c.cno order by sc.degree desc)rank_id
from course c
inner join score sc on c.cno=sc.cno
inner join student s on sc.sno=s.sno
)a where rank_id<=3;
部分参考:https://blog.csdn.net/qq_41338740/article/details/81034134