【1】-Mysql之超經典SQL練習題

文章下方有視頻鏈接

一、數據表

--1.學生表 Student(SId,Sname,Sage,Ssex)
--SId 學生編號,Sname 學生姓名,Sage 出生年月,Ssex 學生性別
--2.課程表 Course(CId,Cname,TId) --CId --課程編號,Cname 課程名稱,TId 教師編號
--3.教師表 Teacher(TId,Tname) --TId 教師編號,Tname 教師姓名
--4.成績表 SC(SId,CId,score) --SId 學生編號,CId 課程編號,score 分數

二、創建測試數據

1.學生表 Student

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('09' , '張三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2017-12-30' , '女');
insert into Student values('12' , '趙六' , '2017-01-01' , '女');
insert into Student values('13' , '孫七' , '2018-01-01' , '女');
Student

2.科目表 Course

create table Course(CId varchar(10),Cname nvarchar(10),TId varchar(10))
insert into Course values('01' , '語文' , '02');
insert into Course values('02' , '數學' , '01');
insert into Course values('03' , '英語' , '03');
course

3.教師表 Teacher

create table Teacher(TId varchar(10),Tname varchar(10))
insert into Teacher values('01' , '張三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
teacher

4.成績表 SC

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);
sc

三、參考答案

1.查詢" 01 "課程比" 02 "課程成績高的學生的信息及課程分數

解題思路:此題用的是99連接法(就是9*9乘法公式一樣的邏輯)。先找出同時選修了01課程和02課程的學生編號和課程對應的成績,再用where設置相同條件。

select *
from (select SId ,score from sc where sc.CId='01') as t1 , 
(select SId ,score from sc where sc.CId='02') as t2
where t1.SId=t2.SId
and   t1.score>t2.score

當然也可以用內聯查詢,我們來試一試:

select * from 
(select sid,cid,score from sc where cid = '01') t1 inner join (select sid,cid,score from sc where cid ='02') t2
on t1.sid=t2.sid and t1.score>t2.score;

1.1 查詢同時存在" 01 "課程和" 02 "課程的情況

選修了01課程的學生與選修了02課程的學生的交集即是同時選修了01、02兩門課程的學生。

select *
from (select SId ,score from sc where sc.CId='01')as t1 , (select SId ,score from sc where sc.CId='02') as t2
where t1.SId=t2.SId

另外一種表達也可以

select *
from (select SId ,score from sc where sc.CId='01')as t1 inner join (select SId ,score from sc where sc.CId='02') as t2
on t1.SId=t2.SId

再看一種寫法:

select *
from (select SId ,score from sc where sc.CId='01')as t1 left  join (select SId ,score from sc where sc.CId='02') as t2
on t1.SId=t2.SId where t2.score is not null;
1.2 查詢存在" 01 "課程但可能不存在" 02 "課程的情況(不存在時顯示為 null )

思路:此題為典型的左連接題,可以將選修了01課程的學生的成績信息左連接于選修了02課程的學生的成績信息。由于采用左連接,所以02課程不存在時自動補充null值。

select *
from (select SId ,score from sc where sc.CId='01')as t1 left join (select SId ,score from sc where sc.CId='02') as t2
on t1.SId=t2.SId

1.3 查詢不存在" 01 "課程但存在" 02 "課程的情況

思路:先找出沒有選修01課程的學生的成績信息,再進一步篩選出同時選修了02課程的學生的成績信息。

select *
from sc
where sc.SId not in (select SId from sc where sc.CId='01')
and  sc.CId='02'

2.查詢平均成績大于等于 60 分的同學的學生編號和學生姓名和平均成績

select sc.sid,st.sname,avg(score) from 
sc,student as st where sc.sid=st.sid group by sc.sid having avg(score)>=60;

來看另外一種思路,有點復雜

select student.*,t1.avgscore
from student inner JOIN(
select sc.SId ,AVG(sc.score)as avgscore
from sc
GROUP BY sc.SId
HAVING AVG(sc.score)>=60)as t1 on student.SId=t1.SId

3.查詢在 SC 表存在成績的學生信息

思路:用sc表中的學生編號對student中的學生信息進行篩選。

select DISTINCT student.*
from student ,sc
where student.SId=sc.SId

4.查詢所有同學的學生編號、學生姓名、選課總數、所有課程的總成績(沒成績的顯示為null)

select st.sid,st.sname,count(sc.cid),sum(sc.score) from student st,sc where st.sid=sc.sid group by sc.sid;

另外一種方法

select student.SId,student.Sname,t1.sumscore,t1.coursecount
from student ,(
select SC.SId,sum(sc.score)as sumscore ,count(sc.CId) as coursecount
from sc
GROUP BY sc.SId) as t1
where student.SId =t1.SId
4.1 查有成績的學生信息
select *
from student
where EXISTS(select * from sc where student.SId=sc.SId)
4.2 查詢「李」姓老師的數量
select count(*)
from teacher
where teacher.Tname like '李%
4.3 查詢學過「張三」老師授課的同學的信息
select student.*
from teacher  ,course  ,student,sc
where teacher.Tname='張三'
and   teacher.TId=course.TId
and   course.CId=sc.CId
and   sc.SId=student.SId
5. 查詢沒有學全所有課程的同學的信息
解法1
select student.*
from sc ,student
where sc.SId=student.SId
GROUP BY sc.SId
Having count(*)<(select count(*) from course)
但這種解法得出來的結果不包括什么課都沒選的同學。
解法2
select DISTINCT student.*
from
(select student.SId,course.CId
from student,course ) as t1 LEFT JOIN (SELECT sc.SId,sc.CId from sc)as t2 on t1.SId=t2.SId and t1.CId=t2.CId,student
where t2.SId is null
and   t1.SId=student.SId

利用笛卡爾積可以把什么課都沒選的同學查詢出來

6.查詢至少有一門課與學號為" 01 "的同學所學相同的同學的信息

思路:從sc表中先找出學號為01的學生選修的課程的編號,以選出來的課程編號作為條件,再從sc表中篩選出至少有一門課與學號為01的同學所學相同的同學的學生學號,最后根據篩選出來的學生編號從student表中再次篩選出相應學生的信息。

select DISTINCT student.*
from  sc ,student
where sc.CId in (select CId from sc where sc.SId='01')
and   sc.SId=student.SId

7.查詢和" 01 "號的同學學習的課程完全相同的其他同學的信息

這道題目也挺難的,這次單獨寫一篇文章講解查詢和01號學生學習的課程完全相同的其他同學的信息

select t1.* from student t1 inner join
(select sc.sid from sc where cid in 
(select cid from sc where sid ='01') and sid !='01'
group by sc.sid having count(distinct cid) =
(select count(distinct cid) from sc where sid='01')) t2 on t1.sid= t2.sid

8.查詢沒學過"張三"老師講授的任一門課程的學生姓名

思路:先查出選了張三將授的課程的學生,再去跟student表進行一個左連接。

 select * from student where student.sid not in
(select distinct student.sid from student,sc where student.sid= sc.sid and  sc.cid = (select course.cid from course,teacher where course.tid=teacher.tid and tname='張三'));

另一種表達:

select * from student where student.SId not in
(select student.SId from student left join sc on student.SId=sc.SId
where EXISTS (select * from teacher ,course where teacher.Tname='張三'
and  teacher.TId=course.TId and   course.CId=sc.CId))

9.查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績

select student.SId,student.Sname,avg(sc.score)
from student ,sc where student.SId=sc.SId and  sc.score<60
GROUP BY sc.SId  HAVING count(*)>=2

10. 檢索" 01 "課程分數小于 60,按分數降序排列的學生信息

select student.*
from student,sc
where sc.CId ='01'
and   sc.score<60
and   student.SId=sc.SId

11.按平均成績從高到低顯示所有學生的所有課程的成績以及平均成績(重點)

select sc.SId,sc.CId,sc.score,t1.avgscore
from  sc left join (select sc.SId,avg(sc.score) as avgscore
from sc
GROUP BY sc.SId) as t1 on sc.SId =t1.SId
ORDER BY t1.avgscore DESC
12.查詢各科成績最高分、最低分和平均分: 以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格率,中等率,優良率,優秀率 及格為>=60,中等為:70-80,優良為:80-90,優秀為:>=90 要求輸出課程號和選修人數,查詢結果按人數降序排列,若人數相同,按課程號升序排列

select sc.CId ,
max(sc.score)as 最高分,min(sc.score)as 最低分,
AVG(sc.score)as 平均分,count(*)as 選修人數,
sum(case when sc.score>=60 then 1 else 0 end )/count(*)as 及格率,
sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end )/count(*)as 中等率,
sum(case when sc.score>=80 and sc.score<90 and sc.score<80 then 1 else 0 end )/count(*)as 優良率,
sum(case when sc.score>=90 then 1 else 0 end )/count(*)as 優秀率
from sc GROUP BY sc.CId
ORDER BY count(*)DESC,sc.CId asc

13.按各科成績進行排序,并顯示排名, Score 重復時保留名次空缺


select sc.CId ,@curRank:=@curRank+1 as rank,sc.score
from (select @curRank:=0) as t ,sc
ORDER BY sc.score desc

14. 按各科成績進行排序,并顯示排名, Score 重復時合并名次

select sc.CId , case when @fontscore=score then @curRank when @fontscore:=score then @curRank:=@curRank+1  end as rank,sc.score
from (select @curRank:=0 ,@fontage:=null) as t ,sc
ORDER BY sc.score desc

15.查詢學生的總成績,并進行排名,總分重復時保留名次空缺



select t1.*,@currank:= @currank+1 as rank
from (select sc.SId, sum(score)
from sc
GROUP BY sc.SId
ORDER BY sum(score) desc) as t1,(select @currank:=0) as t

16. 查詢學生的總成績,并進行排名,總分重復時不保留名次空缺

select t1.*, case when @fontscore=t1.sumscore then @currank  when @fontscore:=t1.sumscore  then @currank:=@currank+1  end as rank
from (select sc.SId, sum(score) as sumscore
from sc
GROUP BY sc.SId
ORDER BY sum(score) desc) as t1,(select @currank:=0,@fontscore:=null) as t

17.統計各科成績各分數段人數:課程編號,課程名稱,[100-85],[85-70],[70-60],[60-0] 及所占百分比



select course.CId,course.Cname,t1.*
from course LEFT JOIN (
select sc.CId,CONCAT(sum(case when sc.score>=85 and sc.score<=100 then 1 else 0 end )/count(*)*100,'%') as '[85-100]',
CONCAT(sum(case when sc.score>=70 and sc.score<85 then 1 else 0 end )/count(*)*100,'%') as '[70-85)',
CONCAT(sum(case when sc.score>=60 and sc.score<70 then 1 else 0 end )/count(*)*100,'%') as '[60-70)',
CONCAT(sum(case when sc.score>=0 and sc.score<60 then 1 else 0 end )/count(*)*100,'%') as '[0-60)'
from sc
GROUP BY sc.CId) as t1 on course.CId=t1.CId

18.查詢各科成績前三名的記錄

思路:前三名轉化為若大于此成績的數量少于3即為前三名。
select *
from sc 
where  (select count(*) from sc as a where sc.CId =a.CId and  sc.score <a.score )<3
ORDER BY CId asc,sc.score desc

19.查詢每門課程被選修的學生數


select sc.CId,count(*)
from sc
GROUP BY sc.CId

20.查詢出只選修兩門課程的學生學號和姓名


select student.SId,student.Sname
from sc,student
where student.SId=sc.SId 
GROUP BY sc.SId
HAVING count(*)=2

21.查詢男生、女生人數

select student.Ssex ,count(*) as 人數
from student
GROUP BY student.Ssex

22.查詢名字中含有「風」字的學生信息

select *
from student
where student.Sname like '%風%'

23.查詢同名同性學生名單,并統計同名人數

select *
from student LEFT JOIN (select Sname,Ssex,COUNT(*)同名人數 from Student group by Sname,Ssex) as t1
on student.Sname =t1.Sname and student.Ssex=t1.Ssex
where t1.同名人數>1

24.查詢 1990 年出生的學生名單

select *
from student
where YEAR(student.Sage)=1990

25.查詢每門課程的平均成績,結果按平均成績降序排列,平均成績相同時,按課程編號升序排列

select sc.CId,AVG(sc.score)
from sc
GROUP BY sc.CId
ORDER BY AVG(sc.score) desc ,sc.CId asc

26.查詢平均成績大于等于 85 的所有學生的學號、姓名和平均成績

select student.SId,student.Sname,t1.avgscore
from student INNER JOIN (select sc.SId ,AVG(sc.score) as avgscore from sc GROUP BY sc.SId HAVING AVG(sc.score)>85) as t1 on
student.SId=t1.SId

27.查詢課程名稱為「數學」,且分數低于 60 的學生姓名和分數



select student.Sname ,t1.score
from student INNER JOIN  (select sc.SId,sc.score
from sc,course
where sc.CId=course.CId
and   course.Cname='數學'
and   sc.score<60)as t1 on student.SId=t1.SId

28.查詢所有學生的課程及分數情況(存在學生沒成績,沒選課的情況)

select student.SId,sc.CId,sc.score from Student  left join sc  on student.SId=sc.SId

29.查詢任何一門課程成績在 70 分以上的姓名、課程名稱和分數

select student.Sname,course.Cname,sc.score
from student , sc  ,course
where sc.score>=70
and  student.SId=sc.SId
and sc.CId=course.CId

30.查詢存在不及格的課程

select DISTINCT sc.CId
from sc
where sc.score <60

31.查詢課程編號為 01 且課程成績在 80 分以上的學生的學號和姓名

select student.SId,student.Sname
from student ,sc
where sc.CId='01'
and  student.SId=sc.SId
and  sc.score>80

32.求每門課程的學生人數


select sc.CId,count(*) as 學生人數
from sc
GROUP BY sc.CId

33.成績不重復,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績


select student.*,sc.score
from student ,course ,teacher ,sc
where course.CId=sc.CId
and course.TId=teacher.TId
and teacher.Tname='張三'
and student.SId =sc.SId
LIMIT 1

34.成績有重復的情況下,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績



select student.*,t1.score
from student INNER JOIN (select sc.SId,sc.score, case when @fontage=sc.score then @rank when @fontage:=sc.score then @rank:=@rank+1 end  as rank
from course ,teacher ,sc,(select @fontage:=null,@rank:=0) as t
where course.CId=sc.CId
and course.TId=teacher.TId
and teacher.Tname='張三'
ORDER BY sc.score DESC) as t1 on student.SId=t1.SId
where t1.rank=1

35.查詢不同課程成績相同的學生的學生編號、課程編號、學生成績


select *
from sc as t1
where exists(select * from sc as t2 where t1.SId=t2.SId and t1.CId!=t2.CId and t1.score =t2.score )

36.查詢每門功成績最好的前兩名

select *
from sc as t1
where (select count(*) from sc as t2 where t1.CId=t2.CId and t2.score >t1.score)<2
ORDER BY t1.CId

37.統計每門課程的學生選修人數(超過 5 人的課程才統計)

select sc.CId as 課程編號,count(*) as 選修人數
from sc
GROUP BY sc.CId
HAVING count(*)>5

38.檢索至少選修兩門課程的學生學號

select DISTINCT t1.SId
from sc as t1
where (select count(* )from sc where t1.SId=sc.SId)>=3

39.查詢選修了全部課程的學生信息


select student.*
from sc ,student
where sc.SId=student.SId
GROUP BY sc.SId
HAVING count(*) = (select DISTINCT count(*) from course )

40.查詢各學生的年齡,只按年份來算

select student.SId as 學生編號,student.Sname  as  學生姓名,TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as 學生年齡
from student

41.按照出生日期來算,當前月日 < 出生年月的月日則,年齡減一



select student.SId as 學生編號,student.Sname  as  學生姓名,TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as 學生年齡
from student

42.查詢本周過生日的學生

select *
from student
where YEARWEEK(student.Sage)=YEARWEEK(CURDATE())

43.查詢下周過生日的學生


select *
from student
where YEARWEEK(student.Sage)=CONCAT(YEAR(CURDATE()),week(CURDATE())+1)

44.查詢本月過生日的學生

select *
from student
where EXTRACT(YEAR_MONTH FROM student.Sage)=EXTRACT(YEAR_MONTH FROM CURDATE())

45.查詢下月過生日的學生

select *
from student
where EXTRACT(YEAR_MONTH FROM student.Sage)=EXTRACT(YEAR_MONTH FROM DATE_ADD(CURDATE(),INTERVAL 1 MONTH))

如果想看視頻講解的話
經典50題視頻精講

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容