已知有以下4張表:mysql
學生表:student(學號,學生姓名,出生年月,性別)面試
成績表:score(學號,課程號,成績)sql
課程表:course(課程號,課程名稱,教師號)數據庫
教師表:teacher(教師號,教師姓名)函數
根據以上信息按照下面要求寫出對應的SQL語句。學習
ps:這些題考察SQL的編寫能力,對於這類型的題目,須要你先把4張表之間的關聯關係搞清楚了,最好的辦法是本身在草稿紙上畫出關聯圖,而後再編寫對應的SQL語句就比較容易了。下圖是我畫的這4張表的關係圖,能夠看出它們之間是經過哪些外鍵關聯起來的:spa
1、建立數據庫和表翻譯
爲了演示題目的運行過程,咱們先按下面語句在客戶端navicat中建立數據庫和表。3d
(如何你還不懂什麼是數據庫,什麼是客戶端navicat,能夠先學習這個:code
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知識:
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知識:
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知識:
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;