如下是SQL面試必備的經典的50道題目,每道題都有博主本人的解題思路和對應的SQL語句。
每道題的思路與答案均爲博主本人主觀理解,僅供參考。面試
環境:MySQL8.0
可視化工具:Navicat函數
一、查詢課程編號爲01的課程比02的課程高的全部學生的學號和成績
解題思路:
(1) 先把課程爲01的學號和成績找出來 as 表a
(2) 再把課程爲02的學號和成績找出來 as 表b
(3) 用inner join將表a和表b按照s_id鏈接起來
(4) 最後用where篩選表a成績大於表b成績的學生編號工具
select a.s_id from (select s_id,s_score from score where c_id='01') as a inner join (select s_id,s_score from score where c_id='02') as b on a.s_id=b.s_id where a.s_score>b.s_score;
二、查詢平均成績大於60分的學生的學號和平均成績
解題思路:
(1) 先用group by對s_id進行分組
(2) 再用having過濾平均分大於60
tips:group by裏的東西必須是select裏的東西,除非是統計函數(avg,max等)code
select s_id,avg(s_score) from score group by s_id having avg(s_score)>60;
三、查詢全部學生的學號、姓名、選課數、總成績
解題思路:
(1) 姓名在student表,成績在score表,所以須要鏈接兩表;student表左鏈接score表,這樣才能保證保留全部學生的信息
(2) 按s_id和s_score進行分組
(3) 選課數使用count(),總成績使用sum(if(...))排序
select a.s_id, a.s_name, count(b.c_id), sum(if(b.s_score is null,0,b.s_score)) from student as a left join score as b on a.s_id=b.s_id group by a.s_id,a.s_name;
四、查詢姓「猴」的老師的人數
解題思路:
(1) 使用like和%進行模糊查詢
(2) 人數使用count()函數ip
select count(t_id) from teacher where t_name like '猴%';
五、查詢沒學過「張三」老師課的學生的學號、姓名
解題思路:
(1) 先找出學過"張三"老師可的學生,這些學生之外的學生就是沒學過"張三"老師課的
(2) 在teacher表中獲取"張三"的t_id,在course表中獲取全部老師t_id和課程c_id,在score表中獲取學生S_id和課程c_id
(3) teacher表與course表按t_id內鏈接,course表與score表按s_id內鏈接,而後選出學生s_id
(4) 最後從student表中中過濾不在上面的學生s_id數學
select s_id,s_name from student where s_id not in( select c.s_id from (select t_id from teacher where t_name='張三') as a inner join (select t_id, c_id from course) as b on a.t_id=b.t_id inner join (select s_id, c_id from score) as c on b.c_id=c.c_id );
六、查詢學過「張三」老師所教的全部課的同窗的學號和姓名
解題思路:
(1) 首先查找"張三"教的全部課程c_id:將teahcer表和course表按t_id內鏈接
(2) 接着查找學過以上課程的學生:將student表和score表按s_id內鏈接
(3) 最後對s_id進行group by,過濾所選課程數量等於"張三"所教課程數量it
select a.s_id,a.s_name from student as a join score as b on a.s_id=b.s_id where b.c_id in ( -- (2)接着查找學過以上課程的學生:將student表和score表按s_id內鏈接 -- (1)首先查找"張三"教的全部課程c_id:將teahcer表和course表按t_id內鏈接 select b.c_id from teacher as a join course as b on a.t_id=b.t_id where a.t_name='張三' ) -- (3)最後對s_id進行group by,過濾所選課程數量等於"張三"所教課程數量 group by a.s_id having count(b.c_id)=( select count(b.c_id) from teacher as a join course as b on a.t_id=b.t_id where a.t_name='張三' );
七、查詢學過編號爲「01」的課程而且也學過編號爲「02」的課程的學生的學號和姓名
解題思路:
(1) 查出學過編號01課程學生s_id做爲表a
(2) 查找學過編號02課程學生s_id做爲表b
(3) 將表a和表b內鏈接,選出學生編號s_id
(4) 最後從student表篩選學生編號包含以上s_id的學生io
select s_id,s_name from student where s_id in ( select a.s_id from (select s_id from score where c_id='01') as a join (select s_id from score where c_id='02') as b on a.s_id=b.s_id );
八、查詢課程編號爲「02」的總成績可視化
select sum(s_score) from score group by c_id having c_id='02';
九、查詢全部課程成績小於60分的學生的學號和姓名
解題思路:
(1) 將score表按s_id進行group by,過濾條件爲課程最大成績小於60(若是最大成績都小於60,那就意味全部成績都小於60)
(2) 從student表中選出學生編號包含以上s_id的學生
select s_id,s_name from student where s_id in ( select s_id from score group by s_id having max(s_score)<60 );
十、查詢沒有學全全部課的學生的學號和姓名
解題思路:
(1) 首先從course表獲取全部課程的總數
(2) 接着student表左鏈接score表並按student.s_id進行group by,過濾條件是每一個學生的課程數量小於第一步的課程總數
(3) 最後從student表中篩選出學生編號包含以上s_id的學生
tips:可能存在一門課也沒有學的學生
select a.s_id,a.s_name from student as a left join score as b on a.s_id=b.s_id group by a.s_id having count(b.c_id)<( select count(c_id) from course );
十一、查詢至少有一門課與學號爲「01」的學生所學課程相同的學生的學號和姓名
解題思路:
(1) 查找出學號爲"01"的學生所學課程編號c_id
(2) student表左鏈接score表,選出c_id有包含上面c_id的學生
(3) 接着對s_id進行group by,過濾s_id!=1,最後選擇學生編號和姓名
select a.s_id,a.s_name from student as a left join score as b on a.s_id=b.s_id where b.c_id in ( select c_id from score where s_id='01' ) group by a.s_id having a.s_id<>'01';
12.查詢和「01」號同窗所學課程徹底相同的其餘同窗的學號
解題思路:
(1) 對score表按s_id進行group by,對每一個s_id的c_id進行group_concat轉換,結果做爲表a
(2) 查出"01"同窗所學課程編號c_id,並進行group_concat轉換,結果做爲表b,將表a與表b按照group_concat的結果進行內鏈接
(3) 以上結果就是與"01"同窗課程徹底相同的同窗(包括"01"),最後篩選學生編號不爲"01"的
select a.s_id from (select s_id,group_concat(c_id order by c_id separator ',') as c_id_str from score group by s_id) as a inner join (select group_concat(c_id order by c_id separator ',') as c_id_str from score where s_id='01') as b on a.c_id_str=b.c_id_str where a.s_id<>'01';
1三、查詢沒學過「張三」老師講授的任一門課程的學生姓名
解題思路:
(1) 查出"張三"的教師編號t_id as表a
(2) 表a按t_id內鏈接course表,course表再按c_id內鏈接score表,便選出學過"張三"課的學生編號s_id
(3) 最後student表中選出不包含上面編號的學生
select s_name from student where s_id not in ( select distinct c.s_id from (select t_id from teacher where t_name='張三') as a inner join (select t_id,c_id from course) as b on a.t_id=b.t_id inner join (select s_id,c_id from score) as c on b.c_id=c.c_id );
1四、查詢有兩門及以上課程不及格的同窗的學號、姓名和平均成績
解題思路:
(1) 篩選score表中score小於60的記錄,而後按s_id進行group by,過濾條件是課程數大於2,最後選出這些s_id
(2) 將上面結果做爲表a內鏈接score表,score表按s_id內鏈接student表,如此一來便可得到有兩門及其以上不及格課程同窗的信息
(3) 對以上聯合表按s_id進行group by,計算每一個s_id的平均分
select a.s_id,c.s_name,avg(b.s_score) from (select s_id from score where s_score<60 group by s_id having count(c_id)>=2) as a inner join (select s_id,s_score from score) as b on a.s_id=b.s_id inner join (select s_id,s_name from student) as c on a.s_id=c.s_id group by a.s_id;
1五、檢索「01」課程分數小於60、按分數降序排列的學生信息
解題思路:
(1) 從score表查找"01"課程分數小於60的學生編號s_id和"01"課程分數,並按按分數降序排序
(2)將上面結果做爲表a與student表內鏈接,最後輸出學生信息
select b.*,a.s_score from (select s_id,s_score from score where c_id='01' and s_score<60 order by s_score desc) as a inner join student as b on a.s_id=b.s_id;
1六、按平均成績從高到低顯示全部學生的全部課程的成績以及平均成績
解題思路:
(1) 將student表與score表左鏈接,能夠獲得學生信息與各科成績
(2) 由於要按照平均成績來排序,因此將第一步的鏈接表按s_id進行group by
(3) 最終顯示格式爲學生編號、學生姓名、01成績、02成績、03成績、平均成績,所以須要使用到case when語句
select a.s_id, a.s_name, -- 若是c_id是01,那麼這一列顯示01課程對應的成績,不然爲空 max(case when b.c_id='01' then b.s_score else null end) as '01', max(case when b.c_id='02' then b.s_score else null end) as '02', max(case when b.c_id='03' then b.s_score else null end) as '03', avg(b.s_score) as avg from (select s_id,s_name from student) as a left join (select s_id,c_id,s_score from score) as b on a.s_id=b.s_id group by a.s_id order by avg desc;
1七、查詢各科成績最高分、最低分和平均分:以以下形式顯示:課程ID,課程name,最高分,最低分,平均分,及格率,中等率,優良率,優秀率(及格爲>=60,中等爲:70-80,優良爲:80-90,優秀爲:>=90)
解題思路:
(1) 顯示列中有分數和課程名字,因此須要將score表與course表內鏈接
(2) 將上一步的鏈接表按課程編號c_id進行group by,分組後便可獲取每一個課程的最高、低分和平均分
(3) 計算及格率中等率等須要使用case when
select a.c_id, a.c_name, max(b.s_score) as '最高分', min(b.s_score) as '最低分', avg(b.s_score) as '平均分', -- 若是成績大於等於60就標記爲1,不然標記爲0,最後計算平均值就獲得對應的合格率 avg(case when b.s_score>=60 then 1 else 0 end) as '及格率', avg(case when b.s_score>=70 and b.s_score<80 then 1 else 0 end) as '中等率', avg(case when b.s_score>=80 and b.s_score<90 then 1 else 0 end) as '優良率', avg(case when b.s_score>=90 then 1 else 0 end) as '優秀率' from course as a inner join score as b on a.c_id=b.c_id group by a.c_id;
1八、按各科成績進行排序,並顯示排名
解題思路:
(1) 由於須要顯示排名,所以這裏須要使用row_number()函數,類似的還有rank()和dense_rank()
(2) 分別顯示課程編號、學生編號、課程成績、排名
select c_id, s_id, s_score, row_number() over (partition by c_id order by s_score desc) as 'rank' from score;
1九、查詢學生的總成績並進行排名
解題思路:
(1) 將score表按學生編號s_id進行group by
(2) 使用row_number()對sum(s_score)進行排序
select s_id, sum(s_score) as sum_score, row_number() over(order by sum(s_score) desc) as 'rank' from score group by s_id;
20、查詢不一樣老師所教不一樣課程的平均分並從高到低顯示
解題思路:
(1) 不一樣老師不一樣課程的平均分:每一個老師教的每一門課的平均分
(2) 須要的字段有老師編號、課程編號、分數,所以須要將course表左鏈接score表
(3) 接着對老師編號和課程編號進行group by
(4) 輸出老師編號、課程編號、分數,按avg(score.s_score)降序排列
select a.t_id, a.c_id, avg(b.s_score) from course as a left join score as b on a.c_id=b.c_id group by a.t_id,a.c_id order by avg(b.s_score) desc;
2一、查詢全部課程的成績第2名到第3名的學生信息及該課程成績
解題思路:
(1) 須要有學生信息和課程成績,所以須要鏈接student表和score表
(2) 使用row_number()函數按課程編號c_id分組並按成績s_score降序排列
(3) 最後從上面的結果中篩選排名爲第2名到第3名的記錄
select * from ( select b.*, a.c_id, a.s_score, row_number() over(partition by a.c_id order by a.s_score desc) as 'rank' from score as a left join student as b on a.s_id=b.s_id ) as info where info.rank in (2,3);
2二、使用分段[100-85]、[85-70]、[70-60]、[<60]來統計各科成績,分別統計各分數段人數、課程ID和課程名稱
解題思路:
(1) 須要的字段有課程名稱和分數,所以須要鏈接course表和score表
(2) 統計各科成績分數段人數,因此要先對課程編號進行group by
(3) 接着就要使用sum()函數和case when來進行分段
tips:也可使用count(),可是count中else後面得是null不能是0
select a.c_id, a.c_name, sum(case when b.s_score<=100 and b.s_score>=85 then 1 else 0 end) as '[100-85]', sum(case when b.s_score<85 and b.s_score>=70 then 1 else 0 end) as '(85-70]', sum(case when b.s_score<70 and b.s_score>=60 then 1 else 0 end) as '(70-60]', sum(case when b.s_score<60 then 1 else 0 end) as '(<60)' from course as a left join score as b on a.c_id=b.c_id group by a.c_id;
2三、查詢學平生均成績及其名次
解題思路:
(1) 學生必定要包含全部學生,所以score中未包含全部學生,所以須要鏈接student表和score表
(2) 要查詢每一個學生的平均成績,就須要對s_id進行group by
(3) 使用rank()函數對平均分排序和打名次
select a.s_id, avg(b.s_score) as avg_score, rank() over(order by avg(b.s_score) desc) as 'rank' from student as a left join score as b on a.s_id=b.s_id group by a.s_id;
2四、查詢各科成績前三名的記錄(不考慮成績並列狀況)
解題思路:
(1) 首先使用row_number()函數對score表中全部課程進行分組並對每門課程的全部學生分數進行排序
(2) 從上面的結果中篩選排序小於等於3的,則爲各科成績前三名
select * from ( select c_id, s_id, s_score, row_number() over(partition by c_id order by s_score desc) as 'row_number' from score ) as info where info.row_number<=3;
2五、查詢每門課程被選修的學生數
解題思路:
(1) 在score表中對c_id進行group by
(2) 用count()函數統計每一個c_Id下的學生數
select c_id,count(s_id) from score group by c_id;
2六、查詢出只有兩門課程的所有學生的學號和姓名
解題思路:
(1) 須要使用到的字段有課程和姓名,所以鏈接student表和score表
(2) 要計算每一個學生的選課數,所以先對s_id進行group by
(3) 通過group by後,過濾條件爲選課數量count(c_id)等於兩門
select a.s_id,a.s_name from student as a left join score as b on a.s_id=b.s_id group by a.s_id having count(c_id)=2;
2七、查詢男生、女生人數
解題思路:
(1) 直接在student表中對性別s_sex進行group by
(2) 隨後使用count()函數便可統計男生人數和女生人數
select s_sex,count(s_id) from student group by s_sex;
2八、查詢名字中含有"風"字的學生信息
解題思路:
(1) 在student表中操做便可
(2) 在篩選條件中使用模糊查詢"%%"
select * from student where s_name like '%風%';
2九、查詢1990年出生的學生名單
解題思路:
(1) 在student表中操做便可
(2) 篩選條件爲出生日期s_birth的年份是1990,便可獲得符合條件的學生
tips:這裏會使用到year()函數,year(datetime)能夠獲得年份
select * from student where year(s_birth)=1990;
30、查詢平均成績大於等於85的全部學生的學號、姓名和平均成績
解題思路:
(1) 須要的字段包含有姓名和成績,所以鏈接student表和score表
(2) 計算平均成績須要先對學號進行group by
(3) 過濾條件爲平均成績avg(s_score)大於等於85分,這樣借的到符合條件的成績
select a.s_id,a.s_name,avg(b.s_score) as avg from student as a left join score as b on a.s_id=b.s_id group by a.s_id having avg(b.s_score)>=85;
3一、查詢每門課程的平均成績,結果按平均成績升序排序,平均成績相同時,按課程號降序排列
解題思路:
(1) 在score表中操做便可
(2) 求每門課的平均成績,須要先對課程編號進行group by
(3) 最後使用order by對平均成績升序排序,平均成績相同時按課程號降序排列
select c_id,avg(s_score) from score group by c_id order by avg(s_score),c_id desc;
3二、查詢課程名稱爲"數學",且分數低於60的學生姓名和分數
解題思路:
(1) 須要使用到的字段有課程名稱、姓名和分數,所以要鏈接student、score和course這三表
(2) 篩選條件爲課程名稱c_name爲"數學",且分數s_score低於60
select a.s_name,b.s_score from student as a left join score as b on a.s_id=b.s_id left join course as c on b.c_id=c.c_id where c.c_name='數學' and b.s_score<60;
3三、查詢全部學生的課程及分數狀況
解題思路:
(1) 題目中說的是全部學生,所以須要使用student表左鏈接score表(由於可能存在沒有選課的學生)
(2) 須要的是每一個學生的狀況,所以先對學生編號進行group by
(3) 返回的字段格式爲學生編號、語文成績、數學成績、英語成績,所以要用到case when
select a.s_id, max(case when c.c_name='語文' then b.s_score else null end) as '語文',-- case when 當課程名字c_name是某門課時則獲得這門課對應的成績s_core max(case when c.c_name='數學' then b.s_score else null end) as '數學', max(case when c.c_name='英語' then b.s_score else null end) as '英語' -- 由於group by要與select列一致,因此case when須要加修飾max from student as a left join score as b on a.s_id=b.s_id left join course as c on b.c_id=c.c_id group by a.s_id;
3四、查詢任何一門課程成績在70分以上的姓名、課程名稱和分數
解題思路:
(1) 首先從score表中選出每一個學生本身所選課程的成績都在70分以上的學生編號
(2) 須要選出的字段有姓名、課程名稱以及分數,所以鏈接student、score和course三張表
(3) 鏈接表的篩選條件爲s_id含有第1步中的那些學生編號
select a.s_name, c.c_name, b.s_score from student as a left join score as b on a.s_id=b.s_id left join course as c on b.c_id=c.c_id where a.s_id in ( select s_id from score group by s_id having min(s_score)>=70 );
3五、查詢學生不及格的課程並按課程號從大到小排列
解題思路:
(1) 在score表中操做便可
select c_id, s_id, s_score from score where s_score<60 order by c_id desc;