一文讓你掌握軟件測試工程師SQL面試題


數據結構說明

已知有如下4張表:

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

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

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

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

准備練習數據

1)創建學生表(student)

CREATE TABLE `student` (
  `學號` varchar(255) NOT NULL,
  `姓名` varchar(50) DEFAULT NULL,
  `出生日期` date DEFAULT NULL,
  `性別` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`學號`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2)創建成績表(score)

CREATE TABLE `score` (
  `學號` varchar(255) NOT NULL,
  `課程號` varchar(255) NOT NULL,
  `成績` float(3,0) DEFAULT NULL,
  PRIMARY KEY (`學號`,`課程號`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3)創建課程表(course)

CREATE TABLE `course` (
  `課程號` varchar(255) NOT NULL,
  `課程名稱` varchar(255) DEFAULT NULL,
  `教師號` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`課程號`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4)教師表(teacher)

CREATE TABLE `teacher` (
  `教師號` varchar(255) NOT NULL,
  `教師姓名` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`教師號`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1)學生表添加數據

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' , '男');

2)成績表添加數據

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);

3)課程表添加數據

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

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

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

4)教師表添加數據

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

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

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

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

簡單查詢

  • 查詢姓“猴”的學生名單
    SELECT * FROM student WHERE 姓名 LIKE '猴%';

  • 查詢姓名中最后一個字是“猴”字的學生名單
    SELECT * FROM student WHERE 姓名 LIKE '%猴';

  • 查詢姓名中帶“猴”字的學生名單
    SELECT * FROM student WHERE 姓名 LIKE '%猴%';

  • 查詢姓“孟”老師的個數
    SELECT COUNT(教師號) FROM teacher WHERE 教師姓名 LIKE '孟%';

匯總分析

1.匯總分析

  • 查詢課程編號為“0002”的總成績
*
分析思路
select 查詢結果 [總成績:匯總函數sum]
from 從哪張表中查找數據[成績表score]
where 查詢條件 [課程號是0002]
*/
SELECT SUM(成績) FROM score WHERE 課程號='0002';
  • 查詢選了課程的學生人數
/*
這個題目翻譯成大白話就是:查詢有多少人選了課程
select 學號,成績表里學號有重復值需要去掉
from 從課程表查找score;
*/
SELECT COUNT(DISTINCT 學號) 選了課程的學生人數 FROM score;

2.分組

  • 查詢各科成績的最高分和最低分, 以如下的形式顯示:課程號,最高分,最低分
/*
分析思路
select 查詢結果 [課程ID:是課程號的別名,最高分:max(成績) ,最低分:min(成績)]
from 從哪張表中查找數據 [成績表score]
where 查詢條件 [沒有]
group by 分組 [各科成績:也就是每門課程的成績,需要按課程號分組]
having 分組后過濾[沒有]
order by 排序desc、asc[沒有]
limit 分頁和限制數量[沒有];
*/
SELECT 課程號,MAX(成績) 最高分,MIN(成績) 最低分
FROM score
GROUP BY 課程號;  -- 是先分組再查詢每組得最高分和最低分
  • 查詢每門課程選修的學生數
SELECT 課程號,COUNT(學號) 選修學生人數
FROM score
GROUP BY 課程號;
  • 查詢男生、女生人數
SELECT 性別,COUNT(學號) 總人數
FROM student
GROUP BY 性別;

3.分組結果的條件

  • 查詢平均成績大於60分學生的學號和平均成績
SELECT 學號,AVG(成績) 平均成績
FROM score
GROUP BY 學號
HAVING AVG(成績)>60;
  • 查詢至少選修兩門課程的學生學號
SELECT 學號,COUNT(課程號) 選修課程數量
FROM score
GROUP BY 學號
HAVING COUNT(課程號)>=2;
  • 查詢同名同姓學生名單並統計同名人數
    分析:條件:怎么算姓名相同?按姓名分組后人數大於等於2,因為同名的人數大於等於2,分析出這一點很重要
SELECT 姓名,COUNT(*)
FROM student
GROUP BY 姓名
HAVING COUNT(*)>=2;
  • 查詢不及格的課程並按課程號從大到小排列
SELECT 課程號
FROM score
WHERE 成績<60
ORDER BY 課程號 DESC;
  • 查詢每門課程的平均成績,結果按平均成績升序排序,平均成績相同時,按課程號降序排列
SELECT 課程號,AVG(成績) 平均成績
FROM score
GROUP BY 課程號
ORDER BY 平均成績 ASC,課程號 DESC;
  • 檢索課程編號為“0004”且分數小於60的學生學號,結果按按分數降序排列
from score
WHERE 課程號='0004' AND 成績<60
ORDER BY 成績 DESC;
  • 統計每門課程的學生選修人數(超過2人的課程才統計),要求輸出課程號和選修人數,查詢結果按人數降序排序,若人數相同,按課程號升序排序
SELECT 課程號,COUNT(學號) 選修人數
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(成績) 平均成績 -- **這是小於60分課程的平均成績,按題目理解是要查詢這個學生全部課程的平均成績**
FROM score
where 成績<60   
GROUP BY 學號
HAVING COUNT(課程號)>=2;

4.查詢結構排序,分組的指定條件

  • 查詢學生的總成績並進行排名
SELECT 學號,SUM(成績) 總成績
from score
GROUP BY 學號
ORDER BY 總成績;
  • 查詢平均成績大於60分的學生的學號和平均成績
SELECT 學號,AVG(成績) 平均成績
FROM score
GROUP BY 學號
HAVING 平均成績>60;

復雜查詢

  • 查詢課程成績小於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);
  • 查詢沒有學全所有課的學生的學號、姓名
/*
查找出學號,條件:沒有學全所有課,也就是該學生選修的課程數 < 總的課程數
【考察知識點】in,子查詢
*/

SELECT 學號
FROM score
GROUP BY 學號
HAVING COUNT(課程號)<3;

SELECT 學號,姓名
FROM student WHERE 學號 IN(SELECT 學號 FROM score GROUP BY 學號 HAVING COUNT(課程號)<3);
  • 查詢出只選修了兩門課程的全部學生的學號和姓名
SELECT 學號,姓名
FROM student WHERE 學號 IN(SELECT 學號 FROM score GROUP BY 學號 HAVING COUNT(課程號)=2);

日期函數

  • 查找1990年出生的學生名單
/*
查找1990年出生的學生名單
學生表中出生日期列的類型是datetime
*/
SELECT * FROM student WHERE YEAR(出生日期)='1990';
  • 查詢各學生的年齡(精確到月份)
/*
【知識點】時間格式轉化​
*/
select 學號 ,timestampdiff(month ,出生日期 ,now())/12 
from student ;
  • 查詢本月過生日的學生
select * 
from student 
where month (出生日期 ) = month(now())+2;​

top-N查詢

工作中會經常遇到這樣的業務問題:

如何找到每個類別下用戶最喜歡的產品是哪個?

如果找到每個類別下用戶點擊最多的5個商品是什么?

這類問題其實就是常見的:分組取每組最大值、最小值,每組最大的N條(top N)記錄。

  • 分組取每組最大值,按課程號分組取成績最大值所在行的數據
-- 可以使用關聯子查詢來實現:
select * 
from score as a 
where 成績 = (
select max(成績) 
from score as b 
where b.課程號 = a.課程號);
  • 分組取每組最小值,按課程號分組取成績最小值所在行的數據
select * 
from score as a 
where 成績 = (
select min(成績) 
from score as b 
where b.課程號 = a.課程號);
  • 每組最大的N條記錄,查詢各科成績前兩名的記錄

第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 將每組選出的數據合並到一起

(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);

多表查詢

  • 查詢所有學生的學號、姓名、選課數、總成績
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.課程號;

多表查詢需要掌握內連接查詢與外連接查詢,參考:
一文讓你徹底理解SQL連接查詢:https://www.cnblogs.com/Uni-Hoang/p/13246587.html

SQL高級功能:窗口函數

暫時延后


來源於:https://zhuanlan.zhihu.com/p/38354000


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM