數據分析師SQL面試必備50題

如下是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;
相關文章
相關標籤/搜索