建表和插入數據
-- 建 表
-- 學 生 表
CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);
-- 課程表
CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);
-- 教師表
CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);
-- 成績表
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
);
-- 插 入 學 生 表 測 試 數 據
insert into Student values('01' , '趙雷','1990-01-01','男');
insert into Student values('02' , '錢電','1990-12-21','男');
insert into Student values('03' , '孫風','1990-05-20','男');
insert into Student values('04' , '李雲','1990-08-06','男');
insert into Student values('05' , '周梅','1991-12-01','女');
insert into Student values('06' , '吳蘭','1992-03-01','女');
insert into Student values('07' , '鄭竹','1989-07-01','女');
insert into Student values('08' , '王菊','1990-01-20','女');
-- 課 程 表 測 試 數 據
insert into Course values('01' , '語文' , '02');
insert into Course values('02' , '數學' , '01');
insert into Course values('03' , '英語' , '03');
-- 教 師 表 測 試 數 據
insert into Teacher values('01' , '張三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
-- 成 績 表 測 試 數 據
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);
題目列表
# 01 查詢“01”課程比“02”課程成績高的學生的信息及課程分數
# 02 查詢“01”課程比“02”課程成績低的學生的信息及課程分數(題目 1 是成績高)
# 03 查詢平均成績大於等於 60 分的同學的學生編號和學生姓名和平均成績
# 04 查詢平均成績小於 60 分的同學的學生編號和學生姓名和平均成績(包括有成績的和無成績的)
# 05 查詢所有同學的學生編號、學生姓名、選課總數、所有課程的總成績
# 06 查詢“李”姓老師的數量
# 07 查詢學過張三老師授課的同學的信息
# 08 找出沒有學過張三老師課程的學生
# 09 查詢學過編號為 01,並且學過編號為 02 課程的學生信息
# 10 查詢學過 01 課程,但是沒有學過 02 課程的學生信息(注意和上面9題目的區別)
# 11 查詢沒有學完全部課程的同學的信息
# 12 查詢至少有一門課與學號為 01 的同學所學相同的同學的信息
# 13 查詢和 01 同學學習的課程完全相同的同學的信息
# 14 查詢沒有修過張三老師講授的任何一門課程的學生姓名
# 15 查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績
# 16 檢索 01 課程分數小於 60,按分數降序排列的學生信息
# 17 按平均成績從高到低(降序)顯示所有學生的所有課程的成績以及平均成績
# 18 查詢各科成績最高分、最低分和平均分:以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格 率,中等率,優良率,優秀率;及格:>=60,中等為:70-80,優良為:80-90,優秀為:>=90
# 19 按照各科成績進行排序,並且顯示排名
# 20 查詢學生的總成績,並進行排名
# 21 查詢不同老師所教不同課程平均分從高到低顯示
# 22 查詢所有課程的成績第 2 名到第 3 名的學生信息及該課程成績
# 23 統計各科成績各分數段人數:課程編號,課程名稱,[100-85],[85-70],[70-60],[0-60] 及所占百分比
# 24 查詢學生的平均成績及名次
# 25 查詢各科成績前三名的記錄
# 26 查詢每門課被選修的學生數
# 27 查詢出只有兩門課程的全部學生的學號和姓名
# 28 查詢男女生人數
# 29 查詢名字中含有 風 字的學生信息
# 30 查詢同名同性的學生名單,並統計同名人數
# 31 查詢 1990 年出生的學生信息
# 32 查詢每門課程的平均成績,結果按平均成績降序排列;平均成績相同時,按課程編號 c_id 升序排列
# 33 查詢平均成績大於等於 85 的所有學生的學號、姓名和平均成績
# 34 查詢課程名稱為數學,且分數低於 60 的學生姓名和分數
# 35 查詢所有學生的課程及分數情況
# 36 查詢任何一門課程成績在 70 分以上的姓名、課程名稱和分數
# 37 查詢不及格的課程
# 38 查詢課程編號為 01 且課程成績大於等於 80 的學生的學號和姓名
# 39 每門課程的學生人數
# 40 查詢選修“張三”老師所授課程的學生中,成績最高的學生信息及其成績
# 41 查詢不同課程成績相同的學生的學生編號、課程編號、學生成績
# 42 查詢每門功成績最好的前兩名
# 43 統計每門課程的學生選修人數(超過 5 人的課程才統計)。要求輸出課程號和選修人數,查詢結果按人數降序排列, 若人數相同,按課程號升序排列
# 44 檢索至少選修兩門課程的學生學號
# 45 查詢選修了全部課程的學生信息
# 46 查詢各學生的年齡:按照出生日期來算,當前月日 < 出生年月的月日則,年齡減 1
# 47 查詢本周過生日的學生
# 48 查詢下周過生日的學生
# 49 查詢本月過生的同學
# 50 查詢下月過生的同學
01
查詢“01”課程比“02”課程成績高的學生的信息及課程分數
| 本質 | 行運算:比較運算 |
|---|---|
| 方法 | 1、直接比較:子查詢 2、弄成兩列:自關聯(注意顯式連接,提升查詢速度) |
| 備注 | 任一科成績缺失不予比較 |
# 1、直接比較:子查詢
select s.*,sc.s_score
from (
select sc1.s_id,sc1.s_score
from score sc1
where sc1.c_id='01'
and sc1.s_score>(select s_score from score where s_id=sc1.s_id and c_id='02')) sc join student s on sc.s_id=s.s_id
# 2.弄成兩列:自關聯(注意顯式連接,提升查詢速度)
select s.*,sc3.s_score
from
(
select sc1.s_id,sc1.s_score
from
( select s_id, s_score from score where c_id = '01' ) sc1
join ( select s_id, s_score from score where c_id = '02' ) sc2 on sc1.s_id = sc2.s_id and sc1.s_score > sc2.s_score
) sc3
join student s on sc3.s_id = s.s_id
# 2.2 直接自關聯
select s.*,sc1.s_score
from student s
join score sc1 on s.s_id=sc1.s_id and sc1.c_id='01'
join score sc2 on s.s_id=sc2.s_id and sc2.c_id='02' and sc1.s_score>sc2.s_score
02
查詢“01”課程比“02”課程成績低的學生的信息及課程分數(題目 1 是成績高)
同上
03
查詢平均成績大於等於 60 分的同學的學生編號和學生姓名和平均成績
| 本質 | 行聚合,后having篩選 |
|---|---|
| 方法 | 直接聚合,后having對聚合函數進行篩選 |
select sc.s_id,s.s_name,round(avg(sc.s_score),0) as score
from score sc join student s on sc.s_id=s.s_id
group by sc.s_id
having score>=60
# 附加題:總分超過200分的同學
select sc.s_id,s.s_name,sum(sc.s_score) as score
from score sc join student s on sc.s_id=s.s_id
group by sc.s_id
having score>200
04
查詢平均成績小於 60 分的同學的學生編號和學生姓名和平均成績(包括有成績的和無成績的)
注:Ctrl+R執行SQL語句
| 本質 | 行聚合,后having篩選 |
|---|---|
| 方法 | 直接聚合,聚合后用having篩選,注意主表 |
| 備注 | 1、主表是學生表,沒有成績的需要包含在內,故left join 2、having可看作聚合函數的where:為空判斷,比較運算,子查詢 3、用ifnull處理空/left join情況 |
# null 判斷
select s.s_id,s.s_name,round(avg(sc.s_score),0) as score
from student s
left join score sc on s.s_id=sc.s_id
group by s.s_id
having score is null or score < 60
# ifnull 函數:更兼容
select s.s_id,s.s_name,round(avg(ifnull(sc.s_score,0)),0) as score
from student s
left join score sc on s.s_id=sc.s_id
group by s.s_id
having score < 60
05
查詢所有同學的學生編號、學生姓名、選課總數、所有課程的總成績
| 本質 | 行聚合 |
|---|---|
| 方法 | 直接聚合,注意對象范圍 |
| 備注 | 主表是學生表,需考慮沒有選課or沒有成績的情況 |
#本題sql
select s.s_id,s.s_name,
count(distinct sc.c_id) as c_num,
sum(sc.s_score) as score
from student s left join score sc on s.s_id=sc.s_id
group by s.s_id
#如果需要聚合后篩選,則使用if和ifnull函數
#if和ifnull是好函數,處理null情況非常方便。注:ifnull搭配值運算函數使用,if函數搭配count函數
select s.s_id,s.s_name,
if(sc.s_id is null,0,count(distinct sc.c_id)) as c_num,
sum(ifnull(sc.s_score,0)) as score
from student s left join score sc on s.s_id=sc.s_id
group by s.s_id
06
查詢“李”姓老師的數量
| 本質 | 行篩選聚合 |
|---|---|
| 方法 | 篩選計數 |
| 備注 |
#問題:like是最優的嗎
#like通配符
SELECT count(DISTINCT t_id) as t_num
FROM Teacher
WHERE t_name like '李%'
#截取姓氏,然后判斷
SELECT count(DISTINCT t_id) as t_num
FROM Teacher
WHERE SUBSTR(t_name,1,1)='李'
07
查詢學過張三老師授課的同學的信息
| 本質 | 行篩選:逐級 |
|---|---|
| 方法 | 表關聯or子查詢 |
| 備注 |
# 逐級子查詢,這樣更好理解
SELECT s.*
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id in(SELECT c_id FROM Course WHERE t_id in(SELECT t_id FROM Teacher WHERE t_name='張三'))
# 表關聯
select s.*
from score sc
join course c on c.c_id=sc.c_id
join teacher t on t.t_id=c.t_id and t.t_name='張三'
join student s on sc.s_id=s.s_id
08
找出沒有學過張三老師課程的學生
| 本質 | 反向行篩選 |
|---|---|
| 方法 | 按照學過篩選,最后取相反情況left join 或right join,且is null |
| 備注 |
# 表關聯
select s.*
from score sc
join course c on c.c_id=sc.c_id
join teacher t on t.t_id=c.t_id and t.t_name='張三'
right join student s on sc.s_id=s.s_id
where sc.s_id is null
# not in,這個好理解
select *
from student
where s_id not in(
select sc.s_id
from score sc
join course c on c.c_id=sc.c_id
join teacher t on t.t_id=c.t_id and t.t_name='張三'
)
09
查詢學過編號為 01,並且學過編號為 02 課程的學生信息
| 本質 | 行篩選:取交集 |
|---|---|
| 方法 | 自關聯 or 子查詢 |
| 備注 |
# 自關聯
SELECT s.*
FROM Score sc1
JOIN Score sc2 on sc1.s_id=sc2.s_id and sc1.c_id='01' and sc2.c_id='02'
JOIN Student s on sc1.s_id=s.s_id
# 子查詢
SELECT s.*
FROM Score sc1
JOIN Student s on sc1.s_id=s.s_id
WHERE sc1.c_id='01'
and sc1.s_id in(SELECT s_id FROM Score sc2 WHERE sc1.s_id=sc2.s_id and sc2.c_id='02')
10
查詢學過 01 課程,但是沒有學過 02 課程的學生信息(注意和上面9題目的區別)
| 本質 | 行篩選:取交集 |
|---|---|
| 方法 | 子查詢,不能使用自關聯,因為一條cid一條記錄,不能用否判斷 |
| 備注 |
# 子查詢
SELECT s.*
FROM Score sc1
JOIN Student s on sc1.s_id=s.s_id
WHERE sc1.c_id='01'
and sc1.s_id not in(SELECT s_id FROM Score sc2 WHERE sc1.s_id=sc2.s_id and sc2.c_id='02')
11
查詢沒有學完全部課程的同學的信息
| 本質 | 行聚合,后having篩選 |
|---|---|
| 方法 | 直接聚合,注意表對象范圍 |
| 備注 | having可看作聚合函數的where:為空判斷,比較運算,子查詢 |
select s.*
from student s
left join score sc on sc.s_id=s.s_id
group by s.s_id
having count(distinct sc.c_id)<(select count(*) from course)
#發現篩選,先篩選出學完全部課程的同學
SELECT *
FROM Student
WHERE s_id not in(SELECT s_id FROM Score GROUP BY s_id HAVING count(c_id)=(SELECT count(*) FROM Course))
12
查詢至少有一門課與學號為 01 的同學所學相同的同學的信息
| 本質 | 行篩選:子查詢 |
|---|---|
| 方法 | 1、學號01所學課程c_id01 2、學號不等於01且c_id in c_id01 |
| 備注 |
select s.*
from score sc
join student s on sc.s_id=s.s_id and sc.s_id<>'01'
where sc.c_id in(select c_id from score where s_id='01')
group by s.s_id
13***
查詢和 01 同學學習的課程完全相同的同學的信息
| 本質 | 行篩選:子查詢 |
|---|---|
| 方法 | 1、學號01所學課程 2、和01所學相同課程且課程數等於01課程數 |
| 備注 | 關鍵是思考方法 |
group_concat()函數用法
group_concat([DISTINCT] 字 段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
# 方法1 課程相同的數量相同
select s.*
from score sc
join student s on sc.s_id=s.s_id
#課程數量相等
where sc.s_id in(SELECT s_id FROM Score WHERE s_id <>'01' GROUP BY s_id HAVING count(distinct c_id)=(select count(distinct c_id) from score where s_id='01'))
#課程相同的數量相同
and c_id in(select c_id from score where s_id='01')
group by s.s_id
having count(distinct sc.c_id)=(select count(distinct c_id) from score where s_id='01')
# 方法2 使用group_concat()函數,如果記錄數比較大,建議采用方法1
select s.*
from student s
join score sc on s.s_id=sc.s_id and sc.s_id<>'01'
group by s.s_id
having group_concat(sc.c_id order by sc.c_id)=
(select group_concat(c_id order by c_id) from score where s_id='01' group by s_id)
14
查詢沒有修過張三老師講授的任何一門課程的學生姓名
| 本質 | 反向行篩選 |
|---|---|
| 方法 | 修過張三老師任一門課即不符合要求 |
| 備注 | 注意表對象是全體學生,主表是學生表,因對s_id篩選,故不用再和score關聯 |
select s_name
from student
where s_id not in(
select s_id from score
where c_id in(select c_id from course where t_id=(select t_id from teacher where t_name='張三')))
15*
查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績
| 本質 | 行篩選並聚合 |
|---|---|
| 方法 | 1、行篩選:及格與否 2、求不及格課程數 3、having篩選 |
| 備注 | 修過才會有及格與否之說,故score為主表 |
# 方式1
select sc.s_id,s.s_name,round(avg(sc.s_score),0) as avg_score
from score sc
join student s on sc.s_id=s.s_id
group by sc.s_id
having sum(if(sc.s_score<60,1,0))>=2
# 方式2 查詢表更小
select sc.s_id,s.s_name,round(avg(sc.s_score),0) as avg_score
from score sc
join student s on sc.s_id=s.s_id and sc.s_score<60
group by sc.s_id
having count(*)>=2
16
檢索 01 課程分數小於 60,按分數降序排列的學生信息
| 本質 | 行篩選並排序 |
|---|---|
| 方法 | 分數<60、分數降序 |
| 備注 | 排序函數區別 1、row_number()over:123 2、rank()over():113 3、dense_rank()over():112 |
SELECT s.*
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id='01'
AND s_score<60
ORDER BY s_score DESC
17
按平均成績從高到低(降序)顯示所有學生的所有課程的成績以及平均成績
| 本質 | 表關聯並排序 |
|---|---|
| 方法 | 找到主表,找到排序字段 |
| 備注 | 如何將排序字段和其他字段關聯是關鍵點 這里的平均成績是所選課程的平均成績 |
# 縱表
SELECT s.s_name,c.c_name,sc.s_score,sc2.avg_score
FROM Student s
JOIN Course c
LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
LEFT JOIN (SELECT s_id,ROUND(AVG(s_score),0) AS avg_score FROM Score GROUP BY s_id) sc2 ON s.s_id=sc2.s_id
ORDER BY sc2.avg_score DESC
#橫表
SELECT s.s_name,
MAX(CASE sc.c_id WHEN '01' THEN sc.s_score END) AS '語文',
MAX(CASE sc.c_id WHEN '02' THEN sc.s_score END) AS '數學',
MAX(CASE sc.c_id WHEN '03' THEN sc.s_score END) AS '英語',
sc2.avg_score as '平均成績'
FROM Student s
JOIN Course c
LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
LEFT JOIN (SELECT s_id,ROUND(AVG(s_score),0) AS avg_score FROM Score GROUP BY s_id) sc2 ON s.s_id=sc2.s_id
GROUP BY s.s_name,sc2.avg_score
ORDER BY sc2.avg_score DESC
18
查詢各科成績最高分、最低分和平均分:以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格 率,中等率,優良率,優秀率;及格:>=60,中等為:70-80,優良為:80-90,優秀為:>=90
| 本質 | 表關聯並聚合 |
|---|---|
| 方法 | 主表course,left join 成績表score,求最值、均值及分組 |
| 備注 | 注意小數位數及百分率符號 |
SELECT c.c_id AS '課程id',c.c_name AS '課程name',
MAX(sc.s_score) AS '最高分',
MIN(sc.s_score) AS '最低分',
ROUND(AVG(sc.s_score),2) AS '平均分',
CONCAT(ROUND(SUM(if(sc.s_score>=60,1,0))/COUNT(sc.s_id)*100,2),'%') AS '及格率',
CONCAT(ROUND(SUM(if(sc.s_score>=70 AND sc.s_score<80,1,0))/COUNT(sc.s_id)*100,2),'%') AS '中等率',
CONCAT(ROUND(SUM(if(sc.s_score>=80 AND sc.s_score<90,1,0))/COUNT(sc.s_id)*100,2),'%') AS '優良率',
CONCAT(ROUND(SUM(if(sc.s_score>=90,1,0))/COUNT(sc.s_id)*100,2),'%') AS '優秀率'
FROM Course c
LEFT JOIN Score sc ON c.c_id=sc.c_id
GROUP BY c.c_id
19
按照各科成績進行排序,並且顯示排名
| 本質 | 分組排序 |
|---|---|
| 方法 | 選擇排序依據並排名 |
| 備注 |
SELECT c.c_name,s.s_name,sc.s_score,
ROW_NUMBER()OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS '排名'
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
JOIN Course c ON sc.c_id=c.c_id
20
查詢學生的總成績,並進行排名
| 本質 | 行聚合后排序 |
|---|---|
| 方法 | sum、排序 |
| 備注 |
SELECT s.s_name,SUM(sc.s_score) AS '總成績',
ROW_NUMBER()OVER(ORDER BY SUM(sc.s_score) DESC) AS '排名'
FROM Student s
LEFT JOIN Score sc ON s.s_id=sc.s_id
GROUP BY s.s_name
21
查詢不同老師所教不同課程平均分從高到低顯示
| 本質 | 表關聯后聚合再排序 |
|---|---|
| 方法 | 主表是教師表teacher和課程表course笛卡爾積,left join 成績表score,求均值后order by |
| 備注 |
SELECT t.t_name,c.c_name,ROUND(AVG(sc.s_score),2) AS '平均分'
FROM Teacher t
JOIN Course c ON t.t_id=c.t_id
LEFT JOIN Score sc ON c.c_id=sc.c_id
GROUP BY t.t_name,c.c_name
ORDER BY AVG(sc.s_score) DESC
22
查詢所有課程的成績第 2 名到第 3 名的學生信息及該課程成績
| 本質 | 行排序后篩選 |
|---|---|
| 方法 | 所有課程成績排名,再取2和3名 |
| 備注 |
SELECT r.c_name,r.rank_num,s.s_name,r.s_score
FROM
(SELECT c.c_name,sc.s_id,sc.s_score,
ROW_NUMBER()OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS rank_num
FROM Course c
LEFT JOIN Score sc ON c.c_id=sc.c_id)r
JOIN Student s ON r.s_id=s.s_id and r.rank_num in(2,3)
23
統計各科成績各分數段人數:課程編號,課程名稱,[100-85],[85-70],[70-60],[0-60] 及所占百分比
| 本質 | 行分組聚合 |
|---|---|
| 方法 | 先列基本:科目、成績,后分組計數 |
| 備注 |
SELECT sc.c_id,c.c_name,
SUM(if(sc.s_score>=85,1,0)) AS '[100-85]人數',
SUM(if(sc.s_score>=70 AND sc.s_score<85,1,0)) AS '[85-70]人數',
SUM(if(sc.s_score>=60 AND sc.s_score<70,1,0)) AS '[70-60]人數',
SUM(if(sc.s_score<60,1,0)) AS '[0-60]人數',
CONCAT(ROUND(SUM(if(sc.s_score>=85,1,0))/COUNT(*)*100,2),'%') AS '[100-85]百分比',
CONCAT(ROUND(SUM(if(sc.s_score>=70 AND sc.s_score<85,1,0))/COUNT(*)*100,2),'%') AS '[85-70]百分比',
CONCAT(ROUND(SUM(if(sc.s_score>=60 AND sc.s_score<70,1,0))/COUNT(*)*100,2),'%') AS '[70-60]百分比',
CONCAT(ROUND(SUM(if(sc.s_score<60,1,0))/COUNT(*)*100,2),'%') AS '[0-60]百分比'
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
GROUP BY sc.c_id
24
查詢學生的平均成績及名次
| 本質 | 行聚合后排序 |
|---|---|
| 方法 | 求平均成績,后排序 |
| 備注 |
SELECT s.s_name,ROUND(AVG(sc.s_score),2) AS '總成績',
ROW_NUMBER()OVER(ORDER BY AVG(sc.s_score) DESC) AS '排名'
FROM Student s
LEFT JOIN Score sc ON s.s_id=sc.s_id
GROUP BY s.s_name
25
查詢各科成績前三名的記錄
| 本質 | 行排序后篩選 |
|---|---|
| 方法 | 各科成績排序,取前3 |
| 備注 |
SELECT r.c_name,r.rank_num,s.s_name,r.s_score
FROM
(SELECT c.c_name,sc.s_id,sc.s_score,
ROW_NUMBER()OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS rank_num
FROM Course c
LEFT JOIN Score sc ON c.c_id=sc.c_id)r
JOIN Student s ON r.s_id=s.s_id and r.rank_num<=3
26
查詢每門課被選修的學生數
| 本質 | 行聚合 |
|---|---|
| 方法 | 成績表按科目對s_id計數 |
| 備注 |
SELECT c.c_name,COUNT(DISTINCT sc.s_id) AS s_num
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_name
27
查詢出只有兩門課程的全部學生的學號和姓名
| 本質 | 行聚合 |
|---|---|
| 方法 | 成績表按學生對c_id計數 |
| 備注 |
SELECT s.s_id,s.s_name
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
GROUP BY s.s_id
HAVING COUNT(DISTINCT sc.c_id)=2
28
查詢男女生人數
| 本質 | 行篩選聚合 |
|---|---|
| 方法 | 學生表student按性別分組計數 |
| 備注 |
SELECT s_sex,COUNT(DISTINCT s_id) AS '人數'
FROM Student
GROUP BY s_sex
29
查詢名字中含有 風 字的學生信息
| 本質 | 模糊篩選 |
|---|---|
| 方法 | |
| 備注 |
SELECT *
FROM Student
WHERE s_name LIKE '%風%'
30
查詢同名同性的學生名單,並統計同名人數
| 本質 | 分組聚合 |
|---|---|
| 方法 | 分組計數后having篩選 |
| 備注 |
SELECT s1.s_name,s1.s_sex,s2.num AS '同名人數'
FROM Student s1
JOIN (SELECT s_name,COUNT(*) AS num FROM Student GROUP BY s_name HAVING COUNT(*)>=2)s2 ON s1.s_name=s2.s_name
GROUP BY s1.s_name,s1.s_sex
HAVING COUNT(*)>=2
31
查詢 1990 年出生的學生信息
| 本質 | 行篩選 |
|---|---|
| 方法 | 獲取出生年份,並篩選 |
| 備注 | DATE()可以將varchar轉成日期型YEAR()函數返回一個指定日期or時間的年份值,范圍為1000到9999,如果日期為零,YEAR()函數返回0 |
SELECT *
FROM Student
WHERE YEAR(DATE(s_birth))=1990
32
查詢每門課程的平均成績,結果按平均成績降序排列;平均成績相同時,按課程編號 c_id 升序排列
| 本質 | 行聚合后排序 |
|---|---|
| 方法 | 對課程求均值,后排序 |
| 備注 | order by后可跟聚合函數 |
SELECT c.c_name,ROUND(AVG(sc.s_score),2) AS '平均分'
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_id
ORDER BY AVG(sc.s_score) DESC,c.c_id ASC
33
查詢平均成績大於等於 85 的所有學生的學號、姓名和平均成績
| 本質 | 行聚合后篩選 |
|---|---|
| 方法 | 對學生求成績均值,后篩選 |
| 備注 |
SELECT s.s_id,s.s_name,ROUND(AVG(sc.s_score),2) AS '平均成績'
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
GROUP BY s.s_id
HAVING AVG(sc.s_score)>=85
34
查詢課程名稱為數學,且分數低於 60 的學生姓名和分數
| 本質 | 行篩選 |
|---|---|
| 方法 | 按要求篩選,用到子查詢 |
| 備注 |
SELECT s.s_name,sc.s_score
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id=(SELECT c_id FROM Course WHERE c_name='數學')
AND s_score<60
35
查詢所有學生的課程及分數情況
| 本質 | 表關聯后聚合 |
|---|---|
| 方法 | 學生表與課程表笛卡爾積,獲取所有學生及所有課程,然后關聯成績表獲取成績,最后聚合 注:成績表為窄表,故外層需要聚合 |
| 備注 |
SELECT s.s_name,
SUM(CASE c.c_name WHEN '語文' THEN sc.s_score ELSE 0 END) AS '語文',
SUM(CASE c.c_name WHEN '數學' THEN sc.s_score ELSE 0 END) AS '數學',
SUM(CASE c.c_name WHEN '英語' THEN sc.s_score ELSE 0 END) AS '英語',
SUM(sc.s_score) AS '總分'
FROM Student s
JOIN Course c
LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
GROUP BY s.s_name
36
查詢任何一門課程成績在 70 分以上的姓名、課程名稱和分數
| 本質 | 行篩選 |
|---|---|
| 方法 | 成績表篩選>70 |
| 備注 |
SELECT s.s_name,c.c_name,sc.s_score
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
JOIN Course c ON sc.s_id=c.c_id
WHERE s_score>70
37
查詢不及格的課程
| 本質 | 行篩選 |
|---|---|
| 方法 | |
| 備注 |
SELECT sc.c_id,c.c_name,sc.s_score
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
WHERE sc.s_score<60
38
查詢課程編號為 01 且課程成績大於等於 80 的學生的學號和姓名
| 本質 | 行篩選 |
|---|---|
| 方法 | |
| 備注 |
SELECT s.s_id,s.s_name
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id='01'
AND s_score>=80
39
每門課程的學生人數
| 本質 | 行聚合 |
|---|---|
| 方法 | |
| 備注 |
SELECT c.c_name,count(DISTINCT sc.s_id) AS '人數'
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_name
40
查詢選修“張三”老師所授課程的學生中,成績最高的學生信息及其成績
| 本質 | 行篩選后聚合 |
|---|---|
| 方法 | 張三老師所授課程中,成績最高(max、order by、row_number()over)的學生 1、max需要關聯表匹配 2、order by和limit 1配合使用,推薦 3、row_number()over需要外層表限制rank_num=1 |
| 備注 |
SELECT s.*,s_score
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id=(SELECT c_id FROM Course WHERE t_id=(SELECT t_id FROM Teacher WHERE t_name='張三'))
ORDER BY s_score DESC
LIMIT 1
41
查詢不同課程成績相同的學生的學生編號、課程編號、學生成績
| 本質 | 行篩選 |
|---|---|
| 方法 | 符合條件的成績:按成績分組,對課程id計數且>2 |
| 備注 |
SELECT *
FROM Score
WHERE s_score in(SELECT s_score FROM Score GROUP BY s_score HAVING COUNT(DISTINCT c_id)>=2)
42
查詢每門功課成績最好的前兩名
| 本質 | 行排序后篩選 |
|---|---|
| 方法 | 這里分組取前兩名,需窗口函數row_number()over |
| 備注 |
SELECT r.*
FROM(
SELECT c_name,s_id,s_score,
ROW_NUMBER()OVER(PARTITION BY c_name ORDER BY s_score DESC) as rank_num
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id)r
WHERE r.rank_num<=2
43
統計每門課程的學生選修人數(超過 5 人的課程才統計)。要求輸出課程號和選修人數,查詢結果按人數降序排列, 若人數相同,按課程號升序排列
| 本質 | 行聚合后排序 |
|---|---|
| 方法 | |
| 備注 |
SELECT c_id,COUNT(DISTINCT s_id) AS '人數'
FROM Score
GROUP BY c_id
ORDER BY '人數' DESC,c_id ASC
44
檢索至少選修兩門課程的學生學號
| 本質 | 行聚合后篩選 |
|---|---|
| 方法 | |
| 備注 |
SELECT s_id
FROM Score
GROUP BY s_id
HAVING COUNT(DISTINCT c_id)>=2
45
查詢選修了全部課程的學生信息
| 本質 | 行聚合后篩選 |
|---|---|
| 方法 | |
| 備注 |
SELECT s.*
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
GROUP BY s.s_id
HAVING COUNT(DISTINCT c_id)=(SELECT COUNT(*) FROM Course)
46
查詢各學生的年齡:按照出生日期來算,當前月日 < 出生年月的月日則,年齡減 1
| 本質 | 行篩選:日期-年月日 |
|---|---|
| 方法 | 年月日獲取year()、month()、day() |
| 備注 |
SELECT *,
CASE
WHEN MONTH(NOW())<MONTH(DATE(s_birth)) THEN
YEAR(NOW())-YEAR(DATE(s_birth))-1
WHEN MONTH(NOW())=MONTH(DATE(s_birth)) AND DAY(NOW())<DAY(DATE(s_birth)) THEN
YEAR(NOW())-YEAR(DATE(s_birth))-1
ELSE
YEAR(NOW())-YEAR(DATE(s_birth))
END AS age
FROM Student
47
查詢本周過生日的學生
| 本質 | 行篩選:日期-周 |
|---|---|
| 方法 | 周獲取week() |
| 備注 |
SELECT *
FROM Student
WHERE WEEK(DATE(s_birth))=WEEK(NOW())
48
查詢下周過生日的學生
| 本質 | 行篩選:日期-周 |
|---|---|
| 方法 | 周獲取week() |
| 備注 |
SELECT *
FROM Student
WHERE WEEK(DATE(s_birth))=WEEK(NOW())+1
49
查詢本月過生的同學
| 本質 | 行篩選:日期-月 |
|---|---|
| 方法 | |
| 備注 |
SELECT *
FROM Student
WHERE MONTH(DATE(s_birth))=MONTH(NOW())
50
查詢下月過生的同學
| 本質 | 行篩選:日期-月 |
|---|---|
| 方法 | |
| 備注 |
SELECT *
FROM Student
WHERE MONTH(DATE(s_birth))=MONTH(NOW())+1
