網(wǎng)上流傳這這樣的50道練習題,以下是我的解法,僅供各位聯(lián)系和參考
數(shù)據(jù)表介紹
--1.學生表
Student(SId,Sname,Sage,Ssex)
--SId 學生編號,Sname 學生姓名,Sage 出生年月,Ssex 學生性別
--2.課程表
Course(CId,Cname,TId)
--CId 課程編號,Cname 課程名稱,TId 教師編號
--3.教師表
Teacher(TId,Tname)
--TId 教師編號,Tname 教師姓名
--4.成績表
SC(SId,CId,score)
--SId 學生編號,CId 課程編號,score 分數(shù)
學生表 Student
create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10));
insert into Student values('01' , '趙雷' , '1990-01-01' , '男');
insert into Student values('02' , '錢電' , '1990-12-21' , '男');
insert into Student values('03' , '孫風' , '1990-12-20' , '男');
insert into Student values('04' , '李云' , '1990-12-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吳蘭' , '1992-01-01' , '女');
insert into Student values('07' , '鄭竹' , '1989-01-01' , '女');
insert into Student values('09' , '張三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2012-06-06' , '女');
insert into Student values('12' , '趙六' , '2013-06-13' , '女');
insert into Student values('13' , '孫七' , '2014-06-01' , '女');
科目表 Course
create table Course(CId varchar(10),Cname nvarchar(10),TId varchar(10));
insert into Course values('01' , '語文' , '02');
insert into Course values('02' , '數(shù)學' , '01');
insert into Course values('03' , '英語' , '03');
教師表 Teacher
create table Teacher(TId varchar(10),Tname varchar(10));
insert into Teacher values('01' , '張三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
成績表 SC
create table SC(SId varchar(10),CId varchar(10),score decimal(18,1));
insert into SC values('01' , '01' , 80);
insert into SC values('01' , '02' , 90);
insert into SC values('01' , '03' , 99);
insert into SC values('02' , '01' , 70);
insert into SC values('02' , '02' , 60);
insert into SC values('02' , '03' , 80);
insert into SC values('03' , '01' , 80);
insert into SC values('03' , '02' , 80);
insert into SC values('03' , '03' , 80);
insert into SC values('04' , '01' , 50);
insert into SC values('04' , '02' , 30);
insert into SC values('04' , '03' , 20);
insert into SC values('05' , '01' , 76);
insert into SC values('05' , '02' , 87);
insert into SC values('06' , '01' , 31);
insert into SC values('06' , '03' , 34);
insert into SC values('07' , '02' , 89);
insert into SC values('07' , '03' , 98);
練習題目
1. 查詢" 01 "課程比" 02 "課程成績高的學生的信息及課程分數(shù)
join課程1成績表和課程2成績表,然后對該表進行篩選
SELECT
c.SId,
d.Sname,
d.Sage,
d.Ssex,
c.S_01,
c.S_02
FROM
(
SELECT
a.SId,
a.score AS S_01,
b.score AS S_02
FROM
(
SELECT
*
FROM
50exercises.sc
WHERE
CId = 01
) AS a
JOIN (
SELECT
*
FROM
50exercises.sc
WHERE
CId = 02
) AS b ON a.SId = b.SId
WHERE
a.score > b.score
) AS c
JOIN 50exercises.student AS d ON c.SId = d.SId
1.1. 查詢同時存在" 01 "課程和" 02 "課程的情況
解題思路 join課程1和課程2的兩張表
SELECT
a.SId,
a.score AS S_01,
b.score AS S_02
FROM
(
SELECT
*
FROM
50exercises.sc
WHERE
CId = 01
) AS a
JOIN (
SELECT
*
FROM
50exercises.sc
WHERE
CId = 02
) AS b ON a.SId = b.SId
1.2. 查詢存在" 01 "課程但可能不存在" 02 "課程的情況(不存在時顯示為 null )
left join課程1和課程2
SELECT
a.SId,
a.score AS S_01,
b.score AS S_02
FROM
(
SELECT
*
FROM
50exercises.sc
WHERE
CId = 01
) AS a
left JOIN (
SELECT
*
FROM
50exercises.sc
WHERE
CId = 02
) AS b ON a.SId = b.SId
1.3. 查詢不存在" 01 "課程但存在" 02 "課程的情況
與1.2思路相似,反之即可
SELECT
a.SId,
a.score AS S_02,
b.score AS S_01
FROM
(
SELECT
*
FROM
50exercises.sc
WHERE
CId = 02
) AS a
LEFT JOIN (
SELECT
*
FROM
50exercises.sc
WHERE
CId = 01
) AS b ON a.SId = b.SId
where b.score IS NULL
2. 查詢平均成績大于等于 60 分的同學的學生編號和學生姓名和平均成績
篩選出平均成績大于60分,和學生表Join
SELECT
b.Sid,
b.Sname,
c.avg_s
FROM
50exercises.student AS b
JOIN (
SELECT
a.SId,
avg(a.score) AS avg_s
FROM
50exercises.sc AS a
GROUP BY
a.Sid
HAVING
avg(a.score) >= 60
) AS c ON b.SId = c.SId
3. 查詢在 SC 表存在成績的學生信息
找出SC表中的學生,然后join學生表
SELECT
a.*
FROM
50exercises.student AS a
JOIN (
SELECT DISTINCT
SId
FROM
50exercises.sc
) AS b ON a.SId = b.SId
4. 查詢所有同學的學生編號、學生姓名、選課總數(shù)、所有課程的總成績(沒成績的顯示為 null )
從學生表left join成績表
SELECT
a.*, b.sum_s
FROM
50exercises.student AS a
LEFT JOIN (
SELECT
SId,
sum(score) AS sum_s
FROM
50exercises.sc
GROUP BY
SId
) AS b ON a.SId = b.SId
4.1 查有成績的學生信息
從成績表開始,然后匹配學生表即可
SELECT
SId,
sum(score) AS sum_s
FROM
50exercises.sc
GROUP BY
SId
5. 查詢「李」姓老師的數(shù)量
找到姓李的老師的表,然后count
SELECT
count(1)
FROM
50exercises.teacher
WHERE Tname LIKE '李%'
6. 查詢學過「張三」老師授課的同學的信息
先找出張三老師教的課,然后找到有這么課成績的學生,然后join學生表
SELECT
*
FROM
50exercises.student AS e
JOIN (
SELECT
c.SId
FROM
50exercises.sc AS c
JOIN (
SELECT
a.CId
FROM
50exercises.course AS a
JOIN (
SELECT
*
FROM
50exercises.teacher
WHERE
Tname = '張三'
) AS b ON a.TId = b.TId
) AS d ON c.CId = d.CId
) AS f ON e.SId = f.SId
7. 查詢沒有學全所有課程的同學的信息
解法1,由于CId是整數(shù),所以可以相加,那么只要找出不是6的或者為空的就可以
SELECT
*
FROM
student AS a
LEFT JOIN (
SELECT
SId,
SUM(CId) AS sum_cid
FROM
sc
GROUP BY
SId
) AS b ON a.SId = b.SId
WHERE
b.sum_cid <> 6
OR b.sum_cid IS NULL
標準解法,上過所有課的人,在sc表中出現(xiàn)的次數(shù)和課程表中課的數(shù)量相同,然后反選即可
SELECT
*
FROM
student
WHERE
student.sid NOT IN (
SELECT
sc.sid
FROM
sc
GROUP BY
sc.sid
HAVING
count(sc.cid) = (SELECT count(cid) FROM course)
)
8. 查詢至少有一門課與學號為" 01 "的同學所學相同的同學的信息
首先得到學號01的同學學過的課程
select `CId`
from `50exercises`.sc
where `SId`= 01
然后取出至少就是篩選課程在這個范圍內(nèi)的記錄,得到Sid
select distinct `SId`
from `50exercises`.sc
where `CId`in(
select `CId`
from `50exercises`.sc
where `SId`= 01
)
最后和信息表組合
select b.*
from
(
select distinct `SId`
from `50exercises`.sc
where `CId`in(
select `CId`
from `50exercises`.sc
where `SId`= 01
)
) as a
join `50exercises`.student as b
on a.SId = b.`SId`
9. 查詢和" 01 "號的同學學習的課程 完全相同的其他同學的信息
select c.*
from `50exercises`.sc as a
join `50exercises`.student as c
on a.`SId`=c.`SId`
group by a.SId
having group_concat(a.CId order by a.CId) = (
select group_concat(b.CId order by b.CId)
from `50exercises`.sc as b
where b.SId = "01"
group by b.SId
)
10. 查詢沒學過"張三"老師講授的任一門課程的學生姓名
select distinct d.`Sname`
from `50exercises`.teacher as a
join `50exercises`.course as b
on a.`TId`= b.`TId` and a.`Tname` != "張三"
join `50exercises`.sc as c
on b.`CId` = c.`CId`
join `50exercises`.student as d
on c.`SId` = d.`SId`
11. 查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績
select a.`SId`,
b.`Sname`,
avg(a.score) as avg_score,
sum(if(a.score < 60,1,0)) as smark
from `50exercises`.sc as a
join `50exercises`.student as b
on a.`SId` = b.`SId`
group by a.`SId`
having smark >=2
12. 檢索" 01 "課程分數(shù)小于 60,按分數(shù)降序排列的學生信息
SELECT
*
FROM
sc AS a
JOIN student AS b ON a.SId = b.SId
WHERE
a.CId = "01"
AND a.score < 60
ORDER BY
a.score DESC
13. 按平均成績從高到低顯示所有學生的所有課程的成績以及平均成績
SELECT
*
FROM
sc AS a
JOIN (
SELECT
Sid,
avg(score) AS AVG_S
FROM
sc
GROUP BY
SId
) AS b ON a.SId = b.Sid
ORDER BY
b.AVG_S DESC
14. 查詢各科成績最高分、最低分和平均分;以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格率,中等率,優(yōu)良率,優(yōu)秀率;及格為>=60,中等為:70-80,優(yōu)良為:80-90,優(yōu)秀為:>=90;要求輸出課程號和選修人數(shù),查詢結(jié)果按人數(shù)降序排列,若人數(shù)相同,按課程號升序排列
SELECT
b.Cname,
b.CId,
max(a.score) AS "最高分",
min(a.score) AS "最低分",
avg(a.score) AS "平均分",
sum(
IF (a.score >= 60 AND a.score < 70, 1, 0)
) / count(DISTINCT Sid) "及格率",
sum(
IF (a.score >= 70 AND a.score < 80, 1, 0)
) / count(DISTINCT Sid) "中等率",
sum(
IF (a.score >= 80 AND a.score < 90, 1, 0)
) / count(DISTINCT Sid) "優(yōu)良率",
sum(IF(a.score >= 90, 1, 0)) / count(DISTINCT Sid) "優(yōu)秀率"
FROM
sc AS a
JOIN course AS b ON a.CId = b.CId
GROUP BY
CId
15. 按各科成績進行排序,并顯示排名, Score 重復時保留名次空缺
SELECT
A.CId,
A.SId,
A.score,
IF (
a.cid =@tmid ,@rank :=@rank + 1 ,@rank := 1
) AS rank ,@tmid := a.cid
FROM
(SELECT * from SC order by cid asc,score DESC) AS A,
(SELECT @rank := 0 ,@tmid := NULL) AS B
15.1 按各科成績進行排序,并顯示排名, Score 重復時合并名次
SELECT
A.CId,
A.SId,
A.score,
CASE
WHEN a.cid <> @tmid THEN
@rank := 1
WHEN a.cid = @tmid
AND a.score <> @tscore THEN
@rank :=@rank + 1
WHEN a.cid = @tmid
AND a.score = @tscore THEN
@rank := @rank
ELSE @rank := 1
END AS rank,
@tmid := a.cid,
@tscore := a.score
FROM
(
SELECT
*
FROM
SC
ORDER BY
cid ASC,
score DESC
) AS A,
(
SELECT
@rank := 1 ,@tmid := NULL ,@tscore := 0
) AS B
16. 查詢學生的總成績,并進行排名,總分重復時保留名次空缺
看了下數(shù)據(jù),沒有總成績相同的學生,檢驗不出效果,所以改成用01課程來檢驗
SELECT
a.SId,
a.all_s,
CASE
WHEN a.all_s <> @tscore then @rank := @rank+1
ELSE @rank = @rank
END as rank,
@tscore := a.all_s
FROM
(
SELECT
SId,
sum(score) AS all_s
FROM
sc
WHERE
Cid = "01"
GROUP BY
SId
ORDER BY
all_s DESC
) AS a,
(SELECT @rank := 0 ,@tscore := 0) AS b
16.1 查詢學生的總成績,并進行排名,總分重復時不保留名次空缺
SELECT
a.SId,
a.all_s,
@rank := @rank+1 as rank
FROM
(
SELECT
SId,
sum(score) AS all_s
FROM
sc
WHERE
Cid = "01"
GROUP BY
SId
ORDER BY
all_s DESC
) AS a,
(SELECT @rank := 0 ) AS b
17. 統(tǒng)計各科成績各分數(shù)段人數(shù):課程編號,課程名稱,[100-85],[85-70],[70-60],[60-0] 及所占百分比
和14題相同
SELECT
b.Cname,
b.CId,
sum(
IF (a.score >= 0 AND a.score < 60, 1, 0)
) / count(DISTINCT Sid) "[0,60)",
sum(
IF (a.score >= 60 AND a.score < 70, 1, 0)
) / count(DISTINCT Sid) "[60,70)",
sum(
IF (a.score >= 70 AND a.score < 85, 1, 0)
) / count(DISTINCT Sid) "[70,85)",
sum(IF(a.score >= 85, 1, 0)) / count(DISTINCT Sid) "[85,100]"
FROM
sc AS a
JOIN course AS b ON a.CId = b.CId
GROUP BY
CId
18. 查詢各科成績前三名的記錄
SELECT
*
FROM
sc
WHERE
(
SELECT
count(*)
FROM
sc AS a
WHERE
sc.cid = a.cid
AND sc.score < a.score
) < 3 ##是不是比自己大的有三條
ORDER BY
cid ASC,
sc.score DESC;
解法2
SELECT
a.sid,
a.cid,
a.score
FROM
sc a
LEFT JOIN sc b ON a.cid = b.cid
AND a.score < b.score
GROUP BY
a.cid,
a.sid
HAVING
count(b.cid) < 3
ORDER BY
a.cid;
19. 查詢每門課程被選修的學生數(shù)
SELECT
CId,
COUNT(DISTINCT SId) AS count_s
FROM
SC
GROUP BY
CId
20. 查詢出只選修兩門課程的學生學號和姓名
SELECT
*
FROM
(
SELECT
SId,
COUNT(DISTINCT CId) AS count_C
FROM
SC
GROUP BY
SId
HAVING
count_C <= 2
) AS a
JOIN student AS b ON a.SId = b.SId
21. 查詢男生、女生人數(shù)
SELECT
Ssex,
COUNT(DISTINCT SId) as Qty
FROM
student
GROUP BY
Ssex
22. 查詢名字中含有「風」字的學生信息
SELECT
*
FROM
student
WHERE
sname LIKE "%風%"
23. 查詢同名同性學生名單,并統(tǒng)計同名人數(shù)
SELECT
sname,
COUNT(DISTINCT sid) AS Qty
FROM
student
GROUP BY
Sname
HAVING
qty > 1
24. 查詢 1990 年出生的學生名單
SELECT
*
FROM
student
WHERE
YEAR (Sage) = 1990
25. 查詢每門課程的平均成績,結(jié)果按平均成績降序排列,平均成績相同時,按課程編號升序排列
SELECT
CId,
avg(score) AS avg_s
FROM
sc
GROUP BY
CId
ORDER BY
avg_s DESC,
CId ASC
26. 查詢平均成績大于等于 85 的所有學生的學號、姓名和平均成績
SELECT
a.SId,
a.Sname,
b.avg_s
FROM
student AS a
JOIN (
SELECT
SId,
avg(score) AS avg_s
FROM
sc
GROUP BY
SId
) AS b ON a.SId = b.SId
27. 查詢課程名稱為「數(shù)學」,且分數(shù)低于 60 的學生姓名和分數(shù)
SELECT
c.Sname,
d.score
FROM
(
SELECT
a.SId,
a.score
FROM
sc AS a
JOIN course AS b ON a.CId = b.CId
WHERE
a.score < 60
AND b.Cname = '數(shù)學'
) AS d
JOIN student AS c ON c.SId = d.SId
28. 查詢所有學生的課程及分數(shù)情況(存在學生沒成績,沒選課的情況)
SELECT
*
FROM
student AS a
JOIN course AS b
LEFT JOIN sc AS c ON a.SId = c.SId
AND b.CId = c.CId
29. 查詢?nèi)魏我婚T課程成績在 70 分以上的姓名、課程名稱和分數(shù)
SELECT
*
FROM
student AS a
JOIN course AS b
LEFT JOIN sc AS c ON a.SId = c.SId
AND b.CId = c.CId
where score > 70
30. 查詢不及格的課程
SELECT
DISTINCT cid
FROM
sc
WHERE
score < 60
31. 查詢課程編號為 01 且課程成績在 80 分以上的學生的學號和姓名
SELECT
b.*
FROM
(
SELECT DISTINCT
Sid
FROM
sc
WHERE
score >= 80
AND Cid = '01'
) AS a
JOIN student AS b ON a.Sid = b.Sid
32. 求每門課程的學生人數(shù)
SELECT
cid,
COUNT(DISTINCT sid)
FROM
sc
GROUP BY
CId
33. 成績不重復,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績
SELECT
*
FROM
teacher AS a
JOIN course AS b ON a.TId = b.TId
AND a.Tname = '張三'
JOIN sc AS c ON b.CId = c.CId
JOIN student AS d ON d.SId = c.SId
HAVING
max(c.score)
34. 成績有重復的情況下,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績
SELECT
*
FROM
teacher AS a
JOIN course AS b ON a.TId = b.TId
AND a.Tname = '張三'
JOIN sc AS c ON b.CId = c.CId
JOIN student AS d ON d.SId = c.SId
WHERE
c.score = (
SELECT
max(c.score)
FROM
teacher AS a
JOIN course AS b ON a.TId = b.TId
AND a.Tname = '張三'
JOIN sc AS c ON b.CId = c.CId
JOIN student AS d ON d.SId = c.SId
)
35. 查詢不同課程成績相同的學生的學生編號、課程編號、學生成績
SELECT
a.cid,
a.sid,
a.score
FROM
sc AS a
INNER JOIN sc AS b ON a.sid = b.sid
AND a.cid != b.cid
AND a.score = b.score
GROUP BY
cid,
sid
36. 查詢每門功成績最好的前兩名
SELECT
*
FROM
sc
WHERE
(
SELECT
count(*)
FROM
sc AS a
WHERE
sc.cid = a.cid
AND sc.score < a.score
) < 3 ##是不是比自己大的有三條
ORDER BY
cid ASC,
sc.score DESC;
37. 統(tǒng)計每門課程的學生選修人數(shù)(超過 5 人的課程才統(tǒng)計)
SELECT
CId,
COUNT(DISTINCT SId) AS Qty
FROM
sc
GROUP BY
CId
HAVING
Qty > 5
38. 檢索至少選修兩門課程的學生學號
SELECT
SId,
COUNT(DISTINCT CId) AS Qty
FROM
sc
GROUP BY
SId
HAVING
Qty >= 2
39. 查詢選修了全部課程的學生信息
SELECT
b.*, COUNT(DISTINCT a.CId) AS Qty
FROM
sc AS a
JOIN student AS b ON a.SId = b.SId
GROUP BY
SId
HAVING
Qty = (
SELECT
COUNT(DISTINCT CId)
FROM
course
)
40. 查詢各學生的年齡,只按年份來算
SELECT
*, YEAR (NOW()) - YEAR (Sage) + 1 AS Age
FROM
student
41. 按照出生日期來算,當前月日 < 出生年月的月日則,年齡減一
SELECT
*, TIMESTAMPDIFF(YEAR, Sage, NOW()) AS Age
FROM
student
42. 查詢本周過生日的學生
SELECT
*
FROM
student
WHERE
WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())
43. 查詢下周過生日的學生
SELECT
*
FROM
student
WHERE
WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())+1
44. 查詢本月過生日的學生
SELECT
*
FROM
student
WHERE
MONTH(Sage) = MONTH(NOW())
45. 查詢下月過生日的學生
SELECT
*
FROM
student
WHERE
MONTH(Sage) = MONTH(NOW())+1