SQL經典50題

已知有以下4張表:mysql

學生表:student(學號,學生姓名,出生年月,性別)面試

成績表:score(學號,課程號,成績)sql

課程表:course(課程號,課程名稱,教師號)數據庫

教師表:teacher(教師號,教師姓名)函數

根據以上信息按照下面要求寫出對應的SQL語句。學習

ps:這些題考察SQL的編寫能力,對於這類型的題目,須要你先把4張表之間的關聯關係搞清楚了,最好的辦法是本身在草稿紙上畫出關聯圖,而後再編寫對應的SQL語句就比較容易了。下圖是我畫的這4張表的關係圖,能夠看出它們之間是經過哪些外鍵關聯起來的:spa

1、建立數據庫和表翻譯

爲了演示題目的運行過程,咱們先按下面語句在客戶端navicat中建立數據庫和表。3d

(如何你還不懂什麼是數據庫,什麼是客戶端navicat,能夠先學習這個:code

從零學會SQL:入門

1.建立表

1)建立學生表(student)

按下圖在客戶端navicat裏建立學生表

學生表的「學號」列設置爲主鍵約束,下圖是每一列設置的數據類型和約束

建立完表,點擊「保存」

2)建立成績表(score)

一樣的步驟,建立"成績表「。「課程表的「學號」和「課程號」一塊兒設置爲主鍵約束(聯合主鍵),「成績」這一列設置爲數值類型(float,浮點數值)

3)建立課程表(course)

課程表的「課程號」設置爲主鍵約束

4)教師表(teacher)

教師表的「教師號」列設置爲主鍵約束,

教師姓名這一列設置約束爲「null」(紅框的地方不勾選),表示這一列容許包含空值(null)

2.向表中添加數據

1)向學生表裏添加數據

添加數據的sql

insert into student(學號,姓名,出生日期,性別) 
values('0001' , '猴子' , '1989-01-01' , '男');

insert into student(學號,姓名,出生日期,性別) 
values('0002' , '猴子' , '1990-12-21' , '女');

insert into student(學號,姓名,出生日期,性別) 
values('0003' , '馬雲' , '1991-12-21' , '男');

insert into student(學號,姓名,出生日期,性別) 
values('0004' , '王思聰' , '1990-05-20' , '男');

在客戶端navicat裏的操做

2)成績表(score)

添加數據的sql

insert into score(學號,課程號,成績) 
values('0001' , '0001' , 80);

insert into score(學號,課程號,成績) 
values('0001' , '0002' , 90);

insert into score(學號,課程號,成績) 
values('0001' , '0003' , 99);

insert into score(學號,課程號,成績) 
values('0002' , '0002' , 60);

insert into score(學號,課程號,成績) 
values('0002' , '0003' , 80);

insert into score(學號,課程號,成績) 
values('0003' , '0001' , 80);

insert into score(學號,課程號,成績) 
values('0003' , '0002' , 80);

insert into score(學號,課程號,成績) 
values('0003' , '0003' , 80);

客戶端navicat裏的操做

3)課程表

添加數據的sql

insert into course(課程號,課程名稱,教師號)
values('0001' , '語文' , '0002');

insert into course(課程號,課程名稱,教師號)
values('0002' , '數學' , '0001');

insert into course(課程號,課程名稱,教師號)
values('0003' , '英語' , '0003');

客戶端navicat裏的操做

4)教師表裏添加數據

添加數據的sql

-- 教師表:添加數據
insert into teacher(教師號,教師姓名) 
values('0001' , '孟扎扎');

insert into teacher(教師號,教師姓名) 
values('0002' , '馬化騰');

-- 這裏的教師姓名是空值(null)
insert into teacher(教師號,教師姓名) 
values('0003' , null);

-- 這裏的教師姓名是空字符串('')
insert into teacher(教師號,教師姓名) 
values('0004' , '');

客戶端navicat裏操做

添加結果

3、50道面試題

爲了方便學習,我將50道面試題進行了分類

1.簡單查詢

查詢姓「猴」的學生名單

查詢姓「孟」老師的個數

select count(教師號)
from teacher
where 教師姓名 like '孟%';

若是上面題目不會作,能夠複習這部分涉及到的sql知識:

從零學會SQL:簡單查詢​www.zhihu.com圖標

2.彙總分析

面試題:查詢課程編號爲「0002」的總成績

*
分析思路
select 查詢結果 [總成績:彙總函數sum]
from 從哪張表中查找數據[成績表score]
where 查詢條件 [課程號是0002]
*/
select sum(成績)
from score
where 課程號 = '0002';

查詢選了課程的學生人數

/*
這個題目翻譯成大白話就是:查詢有多少人選了課程
select 學號,成績表裏學號有重複值須要去掉
from 從課程表查找score;
*/
select count(distinct 學號) as 學生人數 
from score;

查詢各科成績最高和最低的分, 以以下的形式顯示:課程號,最高分,最低分

/*
分析思路
select 查詢結果 [課程ID:是課程號的別名,最高分:max(成績) ,最低分:min(成績)]
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [沒有]
group by 分組 [各科成績:也就是每門課程的成績,須要按課程號分組];
*/
select 課程號,max(成績) as 最高分,min(成績) as 最低分
from score
group by 課程號;

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

/*
分析思路
select 查詢結果 [課程號,選修該課程的學生數:彙總函數count]
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [沒有]
group by 分組 [每門課程:按課程號分組];
*/
select 課程號, count(學號)
from score
group by 課程號;

查詢男生、女生人數

/*
分析思路
select 查詢結果 [性別,對應性別的人數:彙總函數count]
from 從哪張表中查找數據 [性別在學生表中,因此查找的是學生表student]
where 查詢條件 [沒有]
group by 分組 [男生、女生人數:按性別分組]
having 對分組結果指定條件 [沒有]
order by 對查詢結果排序[沒有];
*/
select 性別,count(*)
from student
group by 性別;

查詢平均成績大於60分學生的學號和平均成績

/* 
題目翻譯成大白話:
平均成績:展開來講就是計算每一個學生的平均成績
這裏涉及到「每一個」就是要分組了
平均成績大於60分,就是對分組結果指定條件

分析思路
select 查詢結果 [學號,平均成績:彙總函數avg(成績)]
from 從哪張表中查找數據 [成績在成績表中,因此查找的是成績表score]
where 查詢條件 [沒有]
group by 分組 [平均成績:先按學號分組,再計算平均成績]
having 對分組結果指定條件 [平均成績大於60分]
*/
select 學號, avg(成績)
from score
group by 學號
having avg(成績)>60;

查詢至少選修兩門課程的學生學號

/* 
翻譯成大白話:
第1步,須要先計算出每一個學生選修的課程數據,須要按學號分組
第2步,至少選修兩門課程:也就是每一個學生選修課程數目>=2,對分組結果指定條件

分析思路
select 查詢結果 [學號,每一個學生選修課程數目:彙總函數count]
from 從哪張表中查找數據 [課程的學生學號:課程表score]
where 查詢條件 [至少選修兩門課程:須要先計算出每一個學生選修了多少門課,須要用分組,因此這裏沒有where子句]
group by 分組 [每一個學生選修課程數目:按課程號分組,而後用匯總函數count計算出選修了多少門課]
having 對分組結果指定條件 [至少選修兩門課程:每一個學生選修課程數目>=2]
*/
select 學號, count(課程號) as 選修課程數目
from score
group by 學號
having count(課程號)>=2;

查詢同名同性學生名單並統計同名人數

/* 
翻譯成大白話,問題解析:
1)查找出姓名相同的學生有誰,每一個姓名相同窗生的人數
查詢結果:姓名,人數
條件:怎麼算姓名相同?按姓名分組後人數大於等於2,由於同名的人數大於等於2
分析思路
select 查詢結果 [姓名,人數:彙總函數count(*)]
from 從哪張表中查找數據 [學生表student]
where 查詢條件 [沒有]
group by 分組 [姓名相同:按姓名分組]
having 對分組結果指定條件 [姓名相同:count(*)>=2]
order by 對查詢結果排序[沒有];
*/

select 姓名,count(*) as 人數
from student
group by 姓名
having count(*)>=2;

查詢不及格的課程並按課程號從大到小排列

/* 
分析思路
select 查詢結果 [課程號]
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [不及格:成績 <60]
group by 分組 [沒有]
having 對分組結果指定條件 [沒有]
order by 對查詢結果排序[課程號從大到小排列:降序desc];
*/
select 課程號
from score 
where 成績<60
order by 課程號 desc;

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

/* 
分析思路
select 查詢結果 [課程號,平均成績:彙總函數avg(成績)]
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [沒有]
group by 分組 [每門課程:按課程號分組]
having 對分組結果指定條件 [沒有]
order by 對查詢結果排序[按平均成績升序排序:asc,平均成績相同時,按課程號降序排列:desc];
*/
select 課程號, avg(成績) as 平均成績
from score
group by 課程號
order by 平均成績 asc,課程號 desc;

檢索課程編號爲「0004」且分數小於60的學生學號,結果按按分數降序排列

/* 
分析思路
select 查詢結果 []
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [課程編號爲「04」且分數小於60]
group by 分組 [沒有]
having 對分組結果指定條件 []
order by 對查詢結果排序[查詢結果按按分數降序排列];
*/
select 學號
from score
where 課程號='04' and 成績 <60
order by 成績 desc;

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

要求輸出課程號和選修人數,查詢結果按人數降序排序,若人數相同,按課程號升序排序

/* 
分析思路
select 查詢結果 [要求輸出課程號和選修人數]
from 從哪張表中查找數據 []
where 查詢條件 []
group by 分組 [每門課程:按課程號分組]
having 對分組結果指定條件 [學生選修人數(超過2人的課程才統計):每門課程學生人數>2]
order by 對查詢結果排序[查詢結果按人數降序排序,若人數相同,按課程號升序排序];
*/
select 課程號, count(學號) as '選修人數'
from score
group by 課程號
having count(學號)>2
order by count(學號) desc,課程號 asc;

查詢兩門以上不及格課程的同窗的學號及其平均成績

/*
分析思路
先分解題目:
1)[兩門以上][不及格課程]限制條件
2)[同窗的學號及其平均成績],也就是每一個學生的平均成績,顯示學號,平均成績
分析過程:
第1步:獲得每一個學生的平均成績,顯示學號,平均成績
第2步:再加上限制條件:
1)不及格課程
2)兩門以上[不及格課程]:課程數目>2


/* 
第1步:獲得每一個學生的平均成績,顯示學號,平均成績
select 查詢結果 [學號,平均成績:彙總函數avg(成績)]
from 從哪張表中查找數據 [涉及到成績:成績表score]
where 查詢條件 [沒有]
group by 分組 [每一個學生的平均:按學號分組]
having 對分組結果指定條件 [沒有]
order by 對查詢結果排序[沒有];
*/
select 學號, avg(成績) as 平均成績
from score
group by 學號;


/* 
第2步:再加上限制條件:
1)不及格課程
2)兩門以上[不及格課程]
select 查詢結果 [學號,平均成績:彙總函數avg(成績)]
from 從哪張表中查找數據 [涉及到成績:成績表score]
where 查詢條件 [限制條件:不及格課程,平均成績<60]
group by 分組 [每一個學生的平均:按學號分組]
having 對分組結果指定條件 [限制條件:課程數目>2,彙總函數count(課程號)>2]
order by 對查詢結果排序[沒有];
*/
select 學號, avg(成績) as 平均成績
from score
where 成績 <60
group by 學號
having count(課程號)>=2;

若是上面題目不會作,能夠複習這部分涉及到的sql知識:

從零學會SQL:彙總分析​www.zhihu.com圖標

3.複雜查詢

查詢全部課程成績小於60分學生的學號、姓名

【知識點】子查詢

1.翻譯成大白話
1)查詢結果:學生學號,姓名
2)查詢條件:全部課程成績 < 60 的學生,須要從成績表裏查找,用到子查詢

第1步,寫子查詢(全部課程成績 < 60 的學生)
select 查詢結果[學號]
from 從哪張表中查找數據[成績表:score]
where 查詢條件[成績 < 60]
group by 分組[沒有]
having 對分組結果指定條件[沒有]
order by 對查詢結果排序[沒有]
limit 從查詢結果中取出指定行[沒有];

select 學號 
from student
where 成績 < 60;

第2步,查詢結果:學生學號,姓名,條件是前面1步查到的學號

select 查詢結果[學號,姓名]
from 從哪張表中查找數據[學生表:student]
where 查詢條件[用到運算符in]
group by 分組[沒有]
having 對分組結果指定條件[沒有]
order by 對查詢結果排序[沒有]
limit 從查詢結果中取出指定行[沒有];
*/
select 學號,姓名
from student
where  學號 in (
select 學號 
from student
where 成績 < 60
);

查詢沒有學全全部課的學生的學號、姓名|

/*
查找出學號,條件:沒有學全全部課,也就是該學生選修的課程數 < 總的課程數
【考察知識點】in,子查詢
*/
select 學號,姓名
from student
where 學號 in(
select 學號 
from score
group by 學號
having count(課程號) < (select count(課程號) from course)
);

查詢出只選修了兩門課程的所有學生的學號和姓名|

select 學號,姓名
from student
where 學號 in(
select 學號
from score
group by 學號
having count(課程號)=2
);

1990年出生的學生名單

/*
查找1990年出生的學生名單
學生表中出生日期列的類型是datetime
*/
select 學號,姓名 
from student 
where year(出生日期)=1990;

查詢各科成績前兩名的記錄

這類問題其實就是常見的:分組取每組最大值、最小值,每組最大的N條(top N)記錄。我專門寫了一篇文章來回答這類問題:

sql面試題:topN問題​mp.weixin.qq.com圖標

若是上面題目不會作,能夠複習這部分涉及到的sql知識:

從零學會SQL:複雜查詢​www.zhihu.com圖標

4.多表查詢

查詢全部學生的學號、姓名、選課數、總成績

selecta.學號,a.姓名,count(b.課程號) as 選課數,sum(b.成績) as 總成績
from student as a left join score as b
on a.學號 = b.學號
group by a.學號;

查詢平均成績大於85的全部學生的學號、姓名和平均成績

select a.學號,a.姓名, avg(b.成績) as 平均成績
from student as a left join score as b
on a.學號 = b.學號
group by a.學號
having avg(b.成績)>85;

查詢學生的選課狀況:學號,姓名,課程號,課程名稱

select a.學號, a.姓名, c.課程號,c.課程名稱
from student a inner join score b on a.學號=b.學號
inner join course c on b.課程號=c.課程號;

查詢出每門課程的及格人數和不及格人數

-- 考察case表達式
select 課程號,
sum(case when 成績>=60 then 1 
     else 0 
    end) as 及格人數,
sum(case when 成績 <  60 then 1 
     else 0 
    end) as 不及格人數
from score
group by 課程號;

使用分段[100-85],[85-70],[70-60],[<60]來統計各科成績,分別統計:各分數段人數,課程號和課程名稱

-- 考察case表達式
select a.課程號,b.課程名稱,
sum(case when 成績 between 85 and 100 
     then 1 else 0 end) as '[100-85]',
sum(case when 成績 >=70 and 成績<85 
     then 1 else 0 end) as '[85-70]',
sum(case when 成績>=60 and 成績<70  
     then 1 else 0 end) as '[70-60]',
sum(case when 成績<60 then 1 else 0 end) as '[<60]'
from score as a right join course as b 
on a.課程號=b.課程號
group by a.課程號,b.課程名稱;

查詢課程編號爲0003且課程成績在80分以上的學生的學號和姓名|

select a.學號,a.姓名
from student  as a inner join score as b on a.學號=b.學號
where b.課程號='0003' and b.成績>80;
相關文章
相關標籤/搜索