000.題目
已知有如下4張表:
學生表:student(學號,學生姓名,出生年月,性別)
成績表:score(學號,課程號,成績)
課程表:course(課程號,課程名稱,教師號)
教師表:teacher(教師號,教師姓名)
根據以上信息按照下面要求寫出對應的SQL語句。
001.創建表
分析表與表的關聯關系:
創建學生表:
創建成績表:
創建課程表:
創建教師表:
002.插入數據
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' , '男');
同理插入其他表的數據:
成績表:
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);
課程表:
insert into course(課程號,課程名稱,教師號) values('0001' , '語文' , '0002'); insert into course(課程號,課程名稱,教師號) values('0002' , '數學' , '0001'); insert into course(課程號,課程名稱,教師號) values('0003' , '英語' , '0003');
教師表:
-- 教師表:添加數據 insert into teacher(教師號,教師姓名) values('0001' , '孟扎扎'); insert into teacher(教師號,教師姓名) values('0002' , '馬化騰'); -- 這里的教師姓名是空值(null) insert into teacher(教師號,教師姓名) values('0003' , null); -- 這里的教師姓名是空字符串('') insert into teacher(教師號,教師姓名) values('0004' , '');
003.50道面試題
簡單查詢
1.查詢姓“猴“的學生名單
SELECT * FROM student WHERE 姓名 LIKE '猴%';
2.查詢姓名總最后一個字是‘猴’的學生
SELECT * FROM student WHERE 姓名 LIKE '%猴';
3.查詢姓名中帶‘猴’的學生名單
SELECT * FROM student WHERE 姓名 LIKE '%猴%';
4.查詢姓“孟”老師的個數
SELECT * FROM teacher WHERE 教師姓名 LIKE '孟%';
匯總分析
5.查詢課程編號為“0002”的總成績
* 分析思路 select 查詢結果 [總成績:匯總函數sum] from 從哪張表中查找數據[成績表score] where 查詢條件 [課程號是0002] */ SELECT SUM(成績) FROM score WHERE 課程號 = '0002';
6.查詢選了課程的學生人數
/* 這個題目翻譯成大白話就是:查詢有多少人選了課程 select 學號,成績表里學號有重復值需要去掉 from 從課程表查找score; */ SELECT COUNT(DISTINCT 學號) as 學生人數 FROM score;
分組
7.查詢各科成績最高和最低的分
/* 分析思路 select 查詢結果 [課程ID:是課程號的別名,最高分:max(成績) ,最低分:min(成績)] from 從哪張表中查找數據 [成績表score] where 查詢條件 [沒有] group by 分組 [各科成績:也就是每門課程的成績,需要按課程號分組]; */ SELECT 課程號,MAX(成績) as 最高分,MIN(成績) as 最低分 FROM score GROUP BY 課程號;
8.查詢每門課程被選修的學生數
/* 分析思路 select 查詢結果 [課程號,選修該課程的學生數:匯總函數count] from 從哪張表中查找數據 [成績表score] where 查詢條件 [沒有] group by 分組 [每門課程:按課程號分組]; */ SELECT 課程號,COUNT(DISTINCT 學號) as 學生數 FROM score GROUP BY 課程號;
9.查詢男生,女生人數
/* 分析思路 select 查詢結果 [性別,對應性別的人數:匯總函數count] from 從哪張表中查找數據 [性別在學生表中,所以查找的是學生表student] where 查詢條件 [沒有] group by 分組 [男生、女生人數:按性別分組] having 對分組結果指定條件 [沒有] order by 對查詢結果排序[沒有]; */ SELECT 性別,COUNT(性別) as 學生數 FROM student GROUP BY 性別; SELECT 性別,COUNT(*) as 學生數 FROM student GROUP BY 性別;
分組結果的條件
10.查詢平均成績大於60分學生的學號和平均成績
/* 題目翻譯成大白話: 平均成績:展開來說就是計算每個學生的平均成績 這里涉及到“每個”就是要分組了 平均成績大於60分,就是對分組結果指定條件 分析思路 select 查詢結果 [學號,平均成績:匯總函數avg(成績)] from 從哪張表中查找數據 [成績在成績表中,所以查找的是成績表score] where 查詢條件 [沒有] group by 分組 [平均成績:先按學號分組,再計算平均成績] having 對分組結果指定條件 [平均成績大於60分] */ SELECT 學號,AVG(成績) as 平均成績 FROM score GROUP BY 學號 HAVING AVG(成績)>60;
11.查詢至少選修兩門課程的學生學號
/* 翻譯成大白話: 第1步,需要先計算出每個學生選修的課程數據,需要按學號分組 第2步,至少選修兩門課程:也就是每個學生選修課程數目>=2,對分組結果指定條件 分析思路 select 查詢結果 [學號,每個學生選修課程數目:匯總函數count] from 從哪張表中查找數據 [課程的學生學號:課程表score] where 查詢條件 [至少選修兩門課程:需要先計算出每個學生選修了多少門課,需要用分組,所以這里沒有where子句] group by 分組 [每個學生選修課程數目:按課程號分組,然后用匯總函數count計算出選修了多少門課] having 對分組結果指定條件 [至少選修兩門課程:每個學生選修課程數目>=2] */ SELECT 學號,COUNT(課程號) as 選修課程數 FROM score GROUP BY 學號 HAVING COUNT(課程號)>=2;
12.查詢同名同姓學生名單並統計同名人數
/* 翻譯成大白話,問題解析: 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;
13.查詢不及格的課程並按課程號從大到小排列
/* 分析思路 select 查詢結果 [課程號] from 從哪張表中查找數據 [成績表score] where 查詢條件 [不及格:成績 <60] group by 分組 [沒有] having 對分組結果指定條件 [沒有] order by 對查詢結果排序[課程號從大到小排列:降序desc]; */ SELECT 課程號 FROM score WHERE 成績<60 ORDER BY 課程號 DESC;
14.查詢每門課程的平均成績,結果按平均成績升序排序,平均成績相同時,按課程號降序排列
/* 分析思路 select 查詢結果 [課程號,平均成績:匯總函數avg(成績)] from 從哪張表中查找數據 [成績表score] where 查詢條件 [沒有] group by 分組 [每門課程:按課程號分組] having 對分組結果指定條件 [沒有] order by 對查詢結果排序[按平均成績升序排序:asc,平均成績相同時,按課程號降序排列:desc]; */ SELECT 課程號,AVG(成績) as 平均成績 FROM score GROUP BY 課程號 ORDER BY 平均成績 ASC,課程號 DESC;
15.檢索課程編號為“0004”且分數小於60的學生學號,結果按按分數降序排列
/* 分析思路 select 查詢結果 [] from 從哪張表中查找數據 [成績表score] where 查詢條件 [課程編號為“04”且分數小於60] group by 分組 [沒有] having 對分組結果指定條件 [] order by 對查詢結果排序[查詢結果按按分數降序排列]; */ SELECT 學號 FROM score WHERE 課程號='0004' AND 成績<60 ORDER BY 成績 DESC;
16.統計每門課程的學生選修人數(超過2人的課程才統計),要求輸出課程號和選修人數,查詢結果按人數降序排序,若人數相同,按課程號升序排序
/* 分析思路 select 查詢結果 [要求輸出課程號和選修人數] from 從哪張表中查找數據 [] where 查詢條件 [] group by 分組 [每門課程:按課程號分組] having 對分組結果指定條件 [學生選修人數(超過2人的課程才統計):每門課程學生人數>2] order by 對查詢結果排序[查詢結果按人數降序排序,若人數相同,按課程號升序排序]; */ SELECT 課程號,COUNT(學號) as 選修人數 FROM score GROUP BY 課程號 HAVING 選修人數>2 ORDER BY 選修人數 DESC,課程號 ASC;
17.查詢兩門以上不及格課程的同學的學號及其平均成績
/* 分析思路 先分解題目: 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;
匯總分析
18.查詢學生的總成績並進行排名
【知識點】分組查詢 /* 分析思路 select 查詢結果 [總成績:sum(成績), 學號] from 從哪張表中查找數據 [成績表score] where 查詢條件 [沒有] group by 分組 [學生的總成績:按照每個學生學號進行分組] order by 排序 [按照總成績進行排序:sum(成績)]; /* SELECT 學號,SUM(成績) as 總成績 FROM score GROUP BY 學號 ORDER BY 總成績 DESC;
19.查詢平均成績大於60分的學生的學號和平均成績
【知識點】分組+條件 /* 分析思路 select 查詢結果 [學號, 平均成績: avg(成績)] from 從哪張表中查找數據 [成績表score] where 查詢條件 [沒有] group by 分組 [學號] having 分組條件 [平均成績大於60分:avg(成績 ) >60] order by 排序 [沒有]; /* SELECT 學號,AVG(成績) as 平均成績 FROM score GROUP BY 學號 HAVING 平均成績>60;
復雜查詢
20.查詢所有課程成績小於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 score WHERE 成績<60);
21.查詢沒有學全所有課的學生的學號、姓名
/* 查找出學號,條件:沒有學全所有課,也就是該學生選修的課程數 < 總的課程數 【考察知識點】in,子查詢 */ SELECT 學號,姓名 FROM student WHERE 學號 IN ( SELECT 學號 FROM score GROUP BY 學號 HAVING COUNT(學號)<( SELECT COUNT(課程號) FROM course ));
22.查詢出只選修了兩門課程的全部學生的學號和姓名
SELECT 學號,姓名 FROM student WHERE 學號 IN ( SELECT 學號 FROM score GROUP BY 學號 HAVING COUNT(課程號)=2);
23.1990年出生的學生名單
/* 查找1990年出生的學生名單 學生表中出生日期列的類型是datetime */ SELECT * FROM student WHERE 出生日期 LIKE "1990%"; SELECT * FROM student WHERE YEAR(出生日期) = 1990;
24.查詢各科成績前兩名的記錄
/* 第1步,查出有哪些組 我們可以按課程號分組,查詢出有哪些組,對應這個問題里就是有哪些課程號 select 課程號,max(成績) as 最大成績 from score group by 課程號; 第2步:先使用order by子句按成績降序排序(desc),然后使用limt子句返回topN(對應這個問題返回的成績前兩名) -- 課程號'0001' 這一組里成績前2名 select * from score where 課程號 = '0001' order by 成績 desc limit 2; 同樣的,可以寫出其他組的(其他課程號)取出成績前2名的sql 第3步,使用union all 將每組選出的數據合並到一起 -- 左右滑動可以可拿到全部sql (select * from score where 課程號 = '0001' order by 成績 desc limit 2) union all (select * from score where 課程號 = '0002' order by 成績 desc limit 2) union all (select * from score where 課程號 = '0003' order by 成績 desc limit 2); */ (SELECT * FROM score WHERE 課程號 = '0001' ORDER BY 成績 DESC LIMIT 2) UNION ALL (SELECT * FROM score WHERE 課程號 = '0002' ORDER BY 成績 DESC LIMIT 2) UNION ALL (SELECT * FROM score WHERE 課程號 = '0003' ORDER BY 成績 DESC LIMIT 2);
25.查詢各學生的年齡(精確到月份)
下面說明了TIMESTAMPDIFF
函數的語法。
TIMESTAMPDIFF(unit,begin,end);
TIMESTAMPDIFF
函數返回begin-end
的結果,其中begin
和end
是DATE或DATETIME表達式。
TIMESTAMPDIFF
函數允許其參數具有混合類型,例如,begin
是DATE
值,end
可以是DATETIME
值。 如果使用DATE
值,則TIMESTAMPDIFF
函數將其視為時間部分為“00:00:00”
的DATETIME
值。
unit
參數是確定(end-begin
)的結果的單位,表示為整數。 以下是有效單位:
- MICROSECOND
- SECOND
- MINUTE
- HOUR
- DAY
- WEEK
- MONTH
- QUARTER
- YEAR
NOW() 函數返回當前的日期和時間。
# 這個自己寫的,只計算了年,錯誤,下面才是正確答案 SELECT 學號,YEAR(CURRENT_DATE) - YEAR(出生日期) as 年齡 FROM student; select 學號 ,timestampdiff(month ,出生日期 ,now())/12 from student ;
26.查詢本月過生日的學生
SELECT * FROM student WHERE MONTH(出生日期) = month(now()); SELECT * FROM student WHERE MONTH(CURRENT_DATE) = MONTH(出生日期);
多表查詢
27.查詢所有學生的學號、姓名、選課數、總成績
SELECT a.學號,a.姓名,COUNT(b.課程號) as 選課數,SUM(b.成績) as 總成績 FROM student as a LEFT JOIN score as b on a.學號 = b.學號 GROUP BY a.學號;
28.查詢平均成績大於85的所有學生的學號、姓名和平均成績
SELECT a.學號,a.姓名,avg(b.成績) as 平均成績 FROM student as a LEFT JOIN score as b on a.學號 = b.學號 GROUP BY a.學號 HAVING 平均成績>85;
29.查詢學生的選課情況:學號,姓名,課程號,課程名稱
# 自己寫的不是很規范,但是結果是對的 SELECT b.學號,b.姓名,b.課程號,a.課程名稱 FROM (SELECT a.學號,a.姓名,b.課程號 FROM student as a INNER JOIN score as b on a.學號 = b.學號) as b INNER JOIN course as a on a.課程號 = b.課程號; # 正確答案 select a.學號, a.姓名, c.課程號,c.課程名稱 from student a inner join score b on a.學號=b.學號 inner join course c on b.課程號=c.課程號;
30.查詢出每門課程的及格人數和不及格人數
-- 考察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 課程號;
31.使用分段[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.課程名稱;
32.查詢課程編號為0003且課程成績在80分以上的學生的學號和姓名
SELECT a.學號,a.姓名 FROM student as a INNER JOIN score as b on a.學號 = b.學號 WHERE b.課程號='0003' AND b.成績>80;
33.行列變化,將score變成如下表形式:
第1步,使用常量列輸出目標表的結構 可以看到查詢結果已經和目標表非常接近了 select 學號,'課程號0001','課程號0002','課程號0003' from score; 第2步,使用case表達式,替換常量列為對應的成績 select 學號, (case 課程號 when '0001' then 成績 else 0 end) as '課程號0001', (case 課程號 when '0002' then 成績 else 0 end) as '課程號0002', (case 課程號 when '0003' then 成績 else 0 end) as '課程號0003' from score; 第3關,分組 分組,並使用最大值函數max取出上圖每個方塊里的最大值 SELECT 學號, MAX(CASE 課程號 WHEN '0001' THEN 成績 ELSE 0 END ) as '課程號0001', MAX(CASE 課程號 WHEN '0002' THEN 成績 ELSE 0 END ) as '課程號0002', MAX(CASE 課程號 WHEN '0003' THEN 成績 ELSE 0 END ) as '課程號0003' FROM score GROUP BY 學號;
多表連接
34.檢索"0001"課程分數小於60,按分數降序排列的學生信息
SELECT a.*,b.成績 FROM student as a INNER JOIN score as b on a.學號=b.學號 WHERE b.成績<60 AND b.課程號='0001' ORDER BY b.成績 DESC;
35.查詢不同老師所教不同課程平均分從高到低顯示
-- 子查詢+內連接 SELECT a.教師號,a.教師姓名,AVG(b.成績) as 平均成績 FROM (SELECT a.教師號,a.教師姓名,b.課程號,b.課程名稱 FROM teacher as a INNER JOIN course as b on a.教師號=b.教師號) as a INNER JOIN score as b on a.課程號=b.課程號 GROUP BY 教師號 ORDER BY 平均成績 DESC; -- 簡寫,可以直接3個表內連接形成一個新表 select a.教師號,a.教師姓名,avg(c.成績) from teacher as a inner join course as b on a.教師號= b.教師號 inner join score c on b.課程號=c.課程號 group by a.教師姓名 order by avg(c.成績) desc;
36.查詢課程名稱為"數學",且分數低於60的學生姓名和分數
SELECT a.姓名,b.成績 as 分數 FROM student as a INNER JOIN score as b on a.學號=b.學號 INNER JOIN course as c on b.課程號=c.課程號 WHERE c.課程名稱='數學' AND b.成績<60;
37.查詢任何一門課程成績在70分以上的姓名、課程名稱和分數
SELECT a.姓名,c.課程名稱,b.成績 as 分數 FROM student as a INNER JOIN score as b on a.學號=b.學號 INNER JOIN course as c on b.課程號=c.課程號 WHERE b.成績>70;
38.查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績
SELECT a.學號,a.姓名,AVG(b.成績) as 平均成績 FROM student as a INNER JOIN score as b on a.學號=b.學號 WHERE b.成績<60 GROUP BY a.學號 HAVING COUNT(a.學號)>=2;
39.查詢不同課程成績相同的學生的學生編號、課程編號、學生成績
SELECT DISTINCT a.學號,a.課程號,a.成績 FROM score as a INNER JOIN score as b on a.學號=b.學號 WHERE b.成績=a.成績 AND a.課程號!=b.課程號;
40.查詢課程編號為“0001”的課程比“0002”的課程成績高的所有學生的學號
SELECT a.學號 FROM (SELECT 學號,成績 FROM score WHERE 課程號='0001') as a INNER JOIN (SELECT 學號,成績 FROM score WHERE 課程號='0002') as b on a.學號=b.學號 WHERE a.成績>b.成績;
41.查詢學過編號為“0001”的課程並且也學過編號為“0002”的課程的學生的學號、姓名
SELECT a.學號,c.姓名 FROM (SELECT 學號,成績 FROM score WHERE 課程號='0001') as a INNER JOIN (SELECT 學號,成績 FROM score WHERE 課程號='0002') as b on a.學號=b.學號 INNER JOIN student c on c.學號=a.學號;
42.查詢學過“孟扎扎”老師所教的所有課的同學的學號、姓名
SELECT a.學號,a.姓名 FROM student as a INNER JOIN score as b on a.學號=b.學號 INNER JOIN course as c on c.課程號=b.課程號 INNER JOIN teacher as d on d.教師號=c.教師號 WHERE d.教師姓名='孟扎扎';
43.查詢沒學過"孟扎扎"老師講授的任一門課程的學生姓名
SELECT 姓名,學號 FROM student WHERE 學號 NOT IN (SELECT a.學號 FROM student as a INNER JOIN score as b on a.學號=b.學號 INNER JOIN course as c on c.課程號=b.課程號 INNER JOIN teacher as d on d.教師號=c.教師號 WHERE d.教師姓名='孟扎扎');
44.查詢選修“孟扎扎”老師所授課程的學生中成績最高的學生姓名及其成績
SELECT a.學號,a.姓名,b.成績 FROM student as a INNER JOIN score as b on a.學號=b.學號 INNER JOIN course as c on c.課程號=b.課程號 INNER JOIN teacher as d on d.教師號=c.教師號 WHERE d.教師姓名='孟扎扎' ORDER BY b.成績 DESC LIMIT 1;
45.查詢至少有一門課與學號為“0001”的學生所學課程相同的學生的學號和姓名
SELECT 學號,姓名 FROM student WHERE 學號 IN (SELECT b.課程號 FROM student as a INNER JOIN score as b on a.學號=b.學號 WHERE b.學號='0001');
46.按平均成績從高到低.顯示所有學生的所有課程的成績以及平均成績,總成績
SELECT a.學號,AVG(a.成績) as 平均成績, MAX(CASE WHEN b.課程名稱='數學' THEN a.成績 ELSE NULL END ) as '數學', MAX(CASE WHEN b.課程名稱='語文' THEN a.成績 ELSE NULL END ) as '語文', MAX(CASE WHEN b.課程名稱='英語' THEN a.成績 ELSE NULL END ) as '英語', SUM(a.成績) as 總成績 FROM score as a INNER JOIN course as b on a.課程號=b.課程號 GROUP BY a.學號 ORDER BY 平均成績 DESC;
SQL高級功能:窗口函數---MySQL版本太低,沒有窗口函數,以后再補
47.查詢學生平均成績及其名次
48.按各科成績進行排序,並顯示排名
49.查詢每門功成績最好的前兩名學生姓名
50.查詢所有課程的成績第2名到第3名的學生信息及該課程成績