通过运行代码:
# SQL CODE
# Create 4 tables and insert data into them
create table Student
(SID varchar(10),
Sname varchar(10),
Sage datetime,
Ssex varchar(10));
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('08' , '王菊' , '1990-01-20' , '女');
create table Course
(CID varchar(10),
Cname varchar(10),
TID varchar(10));
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
create table Teacher
(TID varchar(10),
Tname nvarchar(10));
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
create table SC
(SID varchar(10),
CID varchar(10),
score decimal(18,1));
insert into SC values('01' , '01' , 80);
insert into SC values('01' , '02' , 90);
insert into SC values('01' , '03' , 99);
insert into SC values('02' , '01' , 70);
insert into SC values('02' , '02' , 60);
insert into SC values('02' , '03' , 80);
insert into SC values('03' , '01' , 80);
insert into SC values('03' , '02' , 80);
insert into SC values('03' , '03' , 80);
insert into SC values('04' , '01' , 50);
insert into SC values('04' , '02' , 30);
insert into SC values('04' , '03' , 20);
insert into SC values('05' , '01' , 76);
insert into SC values('05' , '02' , 87);
insert into SC values('06' , '01' , 31);
insert into SC values('06' , '03' , 34);
insert into SC values('07' , '02' , 89);
insert into SC values('07' , '03' , 98);
select Student.* from Student
where SID in
(select a.SID from (select SID from SC where SC.CID = '01' ) as a,
(select SID from SC where SC.CID = '02' ) as b
where a.SID = b.SID)
原理是选出两张表:a表中是选择课程"01"的学生ID,b表中是选择课程"02"的学生ID将两张表通过学生ID内连接可以得到同时选择两门课的学生ID。
select Student.SID, Student.Sname, k.score_01, k.score_02 from Student,
(select a.SID as SID, score_01, score_02 from
(select SID, score as score_01 from SC where CID ='01') as a left join
(select SID, score as score_02 from SC where CID = '02') as b on a.SID = b.SID) as k
where Student.SID = k.SID
原理类似第一题但是注意这里使用的是left join来保证所有选择“01”课程的学生都包括进来。
# 解法一:not in
select * from SC where CID = '02' and SID not in
(select SID from SC where CID ='01')
# 解法二:not exists
select SID from SC where CID = '02' and
not exists(select * from SC as a where a.CID = '01' and a.SID = SC.SID)
这里有两个条件:选择了课程“02”但是没有选课程“01”
select Student.SID, Student.Sname, avg_score from Student inner join
(select SID, avg(score) as avg_score from SC group by SID having avg(score) > 60) as k
on Student.SID = k.SID
这里需要注意到group by和having语句**(不能使用where语句来引导条件)**。
# 解法一: in
select * from Student where SID in
(select distinct SID from SC)
# 解法二: exists
select * from Student where exists(select * from SC where SC.SID = Student.SID)
select Student.SID, Sname, course_num, total_score from Student left join
(select SID, count(*) as course_num, sum(score) as total_score from SC group by SID) as k
on Student.SID = k.SID
select * from Student where exists( select * from SC where SC.SID = Student.SID )
Exists 用于判断:对于每一个Student中的一行数据(一个SID),如果这个( select * from SC where SC.SID = Student.SID
)表格不为空,那么这一行数据会被选择在最后的结果中。
select count(*) from Teacher where Tname like '李%'
这里考察通配符以及like判断语句。
select Distinct Student.* from Student, SC, course, Teacher where
Student.SID = SC.SID and SC.CID = course.CID and course.TID = Teacher.TID and Teacher.Tname = '张三'
另外一种方法是不断地使用in来嵌套判断,但是这里使用多重条件,代码看起来会清晰一点。
select Student.* from Student where SID not in
(select SID from SC group by SID having count(*) = (select count(*) from Course))
往反面思考,学全所有课程的同学的课程数量应当是course表中课程数量。
有一种错误的做法是,
select * from Student where SID in
(select SID from SC group by SID having count(*) < (select count(*) from Course))
这会漏选掉一门课都没有选过的同学。
select * from Student where SID <> '01' and SID in
(select distinct SID from SC where CID in (select CID from SC where SID = '01'))
select Student.* from Student where SID <>'01' and SID in
(select SID from SC where CID in (select CID from SC where SID = '01')
group by SID having count(*) = (select count(*) from SC where SID = '01'))
这题的逻辑比较复杂,在选课范围是“01”号同学的课程里面,所选的课程数目与“01”号同学相同的。可以视为和“01”号同学学了完全相同的课程。
select * from Student where SID not in
(select Distinct SID from SC, Course, Teacher
where SC.CID = course.CID and Course.TID = Teacher.TID and Teacher.Tname = '张三')
想反面的问题,找到选过“张三”老师讲授的课程的学生ID,用not in来排除。
select Student.SID, Student.Sname, avg_score from Student inner join
(select SID, avg(score) as avg_score from SC
where SID in
(select SID from SC where score < 60 group by SID having count(*) > 1) group by SID) as a
on Student.SID = a.SID
select * from Student inner join
(select SID, score as score_01 from SC where CID = '01' and score < 60) as a
on Student.SID = a.SID order by score_01 DESC
注意order by语句和DESC关键词的使用。
select SC.SID, SC.score,SC.CID,avg_score from SC inner join
(select SID, avg(score) as avg_score from SC group by SID) as a
on SC.SID = a.SID order by avg_score DESC
返回的结果中,没有一门课没选的“08”号同学。
select Course.CID,Course.Cname,max_score,min_score, avg_score ,及格率, 中等率, 优良率, 优秀率 from Course inner join
(select CID, max(score) as max_score, min(score) as min_score, avg(score) as avg_score, sum(case when score >=60 then 1 else 0 end)/count(*) as 及格率, sum(case when score >=70 and score < 80 then 1 else 0 end)/count(*) as 中等率,sum(case when score >=80 and score < 90 then 1 else 0 end)/count(*) as 优良率, sum(case when score >=90 then 1 else 0 end)/count(*) as 优秀率 from SC group by CID) as a
on Course.CID = a.CID
需要了解case when语句的用法。
select sc.SID, sc.CID, sc.score, row_number()
over(partition by CID order by score DESC) as rank_num from SC
select sc.SID, sc.CID, sc.score, rank() over(partition by CID order by score DESC) as rank_num from SC
select SID, total_score, row_number() over (order by total_score DESC) as rank_num from (select SID, sum(score) as total_score from SC group by SID) as a
select SID, total_score, row_number() over (order by total_score DESC) as rank_num from (select SID, sum(score) as total_score from SC group by SID) as a
18-21 题 需要我们注意rank()和row_number()函数的用法。
select Course.Cname, a.* from course inner join (select CID,
sum(case when score <=100 and score > 85 then 1 else 0 end )/count(*) as range_100_85,
sum(case when score <=85 and score > 70 then 1 else 0 end )/count(*) as range_85_70,
sum(case when score <=70 and score > 60 then 1 else 0 end )/count(*) as range_70_60,
sum(case when score <=60 then 1 else 0 end)/count(*) as not_pass from SC group by CID) as a
on course.CID = a.CID
select * from (select SID, CID, row_number() over(partition by CID order by score DESC) as rank_num
from SC) as a where a.rank_num < 4
select Student.SID, Student.Sname from Student inner join
(select SID, count(*) from SC group by SID having count(*) = 2) as a
on Student.SID = a.SID
select Ssex,count(*) from Student group by Ssex
select * from Student where Sname like '%风%'
select * from
(select Sname, count(*) as student_num from Student group by Sname) as a
where a.student_num > 1
select * from Student where year(Sage) = 1990
select CID,avg(score) as avg_score from SC group by CID order by avg_score DESC, CID ASC
select Student.SID, Student.Sname, avg_score from Student inner join
(select SID, avg(score) as avg_score from SC group by SID having avg(score) >= 85) as a
on Student.SID = a.SID
select * from Student, SC, Course
where course.Cname = '数学' and SC.score < 60 and Student.SID = SC.SID and SC.CID = Course.CID
select * from Student left join SC
on Student.SID = SC.SID
select Student.Sname, Course.Cname, SC.score from Student, Course, SC where Student.SID not in
(select Distinct SID from SC where SC.score < 70) and Student.SID = SC.SID and SC.CID = Course.CID
select * from Course where CID in
(select Distinct CID from SC where SC.score < 60)
select Student.SID, Student.Sname,a.CID, a.score from Student inner join
(select SID,score,CID from SC where CID = '01' and score >= 80) as a
on Student.SID = a.SID
select CID, count(*) as student_num from SC group by CID
select Student.*, a.score from Student inner join
(select SID, score, row_number() over(partition by CID order by score DESC) as rank_num from SC where CID in (select CID from Teacher,Course where Tname = '张三' and Course.TID = Teacher.TID)) as a
on Student.SID = a.SID where rank_num = 1
select Student.*, a.score from Student inner join
(select SID, score, rank() over(partition by CID order by score DESC) as rank_num from SC where CID in (select CID from Teacher,Course where Tname = '张三' and Course.TID = Teacher.TID)) as a
on Student.SID = a.SID where rank_num = 1
select * from SC where exists(select * from SC as a where a.SID = SC.SID and a.CID <> SC.CID and a.score = SC.score)
考察Exists
的用法。
select Student.*, case when month(now()) < month(Sage) | (month(now()) = month(Sage) and day(now()) < day(Sage)) then year(now()) - year(Sage) - 1 else year(now()) - year(Sage) end as age
from Student
下面是知乎上面的解答:
select student.SId as 学生编号,student.Sname as 学生姓名,Sage, TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as 学生年龄
from student
这里需要注意TIMESTAMPDIFF(interval, datetime1, datetime2),interval是year, month, day,表示间隔最后的单位而两个datetime1,和datetime2则是表示间隔。curdate() 内置函数返回的是当前的日期值。
select * from Student where
week(curdate()) = week(DATE_ADD(Sage,INTERVAL year(curdate()) - year(Sage) YEAR))
使用到了DATE_ADD()
这个函数,函数中的意思是值在Sage的日期上加上间隔的年份(注意这里不能使用timestampdiff()
函数)。
43. 查询下周过生日的学生
select * from Student where
week(curdate()) = week(DATE_ADD(Sage,INTERVAL year(curdate()) - year(Sage) YEAR))-1
类似上一题。
select * from Student where
month(curdate()) = month(Sage)
相对于week这个就比较简单了。
select * from Student where
month(curdate()) = month(Sage)