MySQL经典45题
观看数据蛙经典45题做的笔记,原视频连接如下:https://www.bilibili.com/video/BV1pp4y1Q7Yv?t=1
我一般是看到题目先自己做一遍,再听老师的解题思路,感觉这样效果比较好。
1. 查询01课程比02课程成绩高的学生信息及课程分数
SELECT s.* ,c.`CId`,c.`score`,sc.`CId`,sc.`score`
FROM sc c
JOIN student s
ON s.`SId` = c.`SId`
JOIN sc
ON s.`SId`=sc.`SId`
AND c.cid = 01
AND sc.cid = 02
WHERE c.score > sc.score;
1.1 查询同时存在01课程和02课程的情况
方法1(自写)
SELECT *
FROM student s
INNER JOIN sc c
ON s.`SId`=c.`SId`
INNER JOIN sc
ON sc.`SId` = s.`SId`
AND sc.`CId`=02
AND c.`CId` = 01;
方法2
SELECT *
FROM (SELECT * FROM sc WHERE cid = 01) a
JOIN (SELECT * FROM sc WHERE cid = 02) b
ON a.sid = b.sid
方法3
SELECT *
FROM sc a
INNER JOIN sc b
ON a.sid = b.sid
WHERE a.`CId`=01 AND b.cid = 02;
1.2 查询01存在但可能不存在02 课程的情况(不存在时显示为null)
方法1(自写)
对题目的理解有误差,可能不存在02,也可能存在02。
SELECT *
FROM student s
INNER JOIN sc c
ON s.`SId`=c.`SId` ;
LEFT JOIN sc
ON sc.`SId` = s.`SId`
AND c.`CId` = 01
AND sc.`CId` =02
WHERE c.`CId` = 01 AND sc.cid IS NULL;
修改一下
SELECT *
FROM student s
INNER JOIN sc c
ON s.`SId`=c.`SId`
LEFT JOIN sc
ON sc.`SId` = s.`SId`
AND c.`CId` = 01
AND sc.`CId` =02
WHERE c.`CId` = 01 AND (sc.cid IS NULL OR sc.cid = 02);
方法2
SELECT *
FROM (SELECT *FROM sc WHERE cid = 01) a
LEFT JOIN sc b
ON a.sid = b.sid
AND b.cid = 02;
方法3
SELECT *
FROM sc a
LEFT JOIN sc b
ON a.sid = b.sid
AND b.cid = 02
WHERE a.cid = 01;
1.3 查询不存在01课程,但存在02课程的情况
方法1(自写)
SELECT *
FROM sc a
LEFT JOIN sc b
ON a.sid = b.sid
AND a.cid = 02
WHERE b.cid <> 01 ;
修改后
FROM (SELECT * FROM sc WHERE cid = 02) a
LEFT JOIN (SELECT * FROM sc WHERE cid = 01) b
ON a.sid = b.sid
WHERE b.cid IS NULL;
方法2
SELECT *
FROM (SELECT * FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid = 01)) a
INNER JOIN sc b
ON a.sid = b.sid
AND b.cid =02;
方法3
SELECT *
FROM sc a
WHERE sid NOT IN (SELECT sid FROM sc WHERE cid = 01)
AND cid = 02;
2. 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
方法1(自写)
SELECT s.`SId`,s.`Sname`,AVG(c.`score`)
FROM student s
JOIN sc c
ON s.`SId` = c.`SId`
GROUP BY c.`SId`
HAVING AVG(c.`score`) >= 60;
方法2
SELECT
a.sid,
a.`Sname`,
b.avg_score
FROM student a
JOIN (
SELECT sid , AVG(score) AS avg_score
FROM sc
GROUP BY sid
HAVING AVG(score) >= 60) b
ON a.sid = b.sid;
3.查询在sc表存在成绩的学生信息
方法1(自写)
没有去重
SELECT *
FROM sc c
LEFT JOIN student s
ON s.`SId` = c.`SId`;
修改后
SELECT s.*
FROM sc c
LEFT JOIN student s
ON s.`SId` = c.`SId`
GROUP BY c.`SId`;
方法2
SELECT b.*
FROM sc a
LEFT JOIN student b
ON a.sid = b.`SId`
GROUP BY b.`SId`;
group by 语法:
- 只能查询分组字段,其他字段要以聚合函数的形式被查询出来
所以方法2 不太符合规则
方法3(推荐)
SELECT b.*
FROM (
SELECT sid
FROM sc
GROUP BY sid
) a
LEFT JOIN student b
ON a.sid = b.sid;
4. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示null)
方法1(自写)
SELECT s.`SId`,s.`Sname`,COUNT(c.`CId`),SUM(c.`score`)
FROM student s
JOIN sc c
ON s.`SId`=c.`SId`
GROUP BY c.`SId`;
group by分组应该用主表的参数,否则会丢失部分数据
修改后
SELECT s.`SId`,s.`Sname`,COUNT(c.`CId`),SUM(c.`score`)
FROM student s
LEFT JOIN sc c
ON s.`SId`=c.`SId`
GROUP BY s.`SId`
方法2
SELECT a.sid,a.sname,b.cons,b.sum_core
FROM student a
LEFT JOIN (
SELECT sid,COUNT(cid) AS cons,SUM(score) AS sum_core
FROM sc
GROUP BY sid
) b
ON b.sid = a.sid;
方法3
SELECT
a.sid,
a.sname,
COUNT(b.`CId`) AS cons,
SUM(b.`score`) AS sum_core
FROM student a
LEFT JOIN sc b
ON a.`SId` = b.`SId`
GROUP BY a.`SId`;
5.查询【李】姓老师的数量
方法1(自写)
SELECT COUNT(1),tname
FROM teacher t
WHERE tname LIKE '李%';
6.查询学过【张三】老师授课的同学的信息
方法1(自写)
SELECT s.*,t.`Tname`
FROM student s
JOIN sc c ON s.`SId`=c.`SId`
JOIN course co ON co.`CId` = c.`CId`
JOIN teacher t ON t.`TId` = co.`TId`
WHERE t.`Tname` = '张三';
方法2 (有点复杂化了)
step 1 得到教师和课程的关系
SELECT * FROM course a
INNER JOIN teacher b
ON a.`TId` = b.`TId`
step 2 得到教师和成绩的关系
SELECT * FROM sc c
INNER JOIN (
SELECT a.* , b.`Tname`
FROM course a
INNER JOIN teacher b
ON a.`TId` = b.`TId`) d
ON c.`CId`= d.`CId`
step 3 得到学生和教师的关系
SELECT *
FROM student e
INNER JOIN (
SELECT c.*,d.tid,d.tname
FROM sc c
INNER JOIN (
SELECT a.* , b.`Tname`
FROM course a
INNER JOIN teacher b
ON a.`TId` = b.`TId`) d
ON c.`CId`= d.`CId`) f
ON e.sid = f.sid
WHERE f.tname = '张三';
7.查询没有学全所有课程的同学的信息
方法1(自写)
SELECT *
FROM student s
LEFT JOIN sc c
ON s.`SId` = c.`SId`
GROUP BY s.`SId`
HAVING COUNT(c.`CId`)< MAX(c.`CId`) ;
一门课也没学的同学被遗漏了
反思:max(c.cid)是统计的最大值,而不是数量的最多值
修改后
SELECT *, COUNT(c.`CId`)
FROM student s
LEFT JOIN sc c
ON s.`SId` = c.`SId`
GROUP BY s.`SId`
HAVING COUNT(c.`CId`) < (SELECT COUNT( DISTINCT cid) FROM sc) ;
方法2 (该方法没有包含没选课的同学)
SELECT *
FROM sc a
INNER JOIN student b
ON a.`SId`=b.`SId`
GROUP BY a.`SId`
HAVING COUNT(1) < (SELECT COUNT(1) FROM course);
8. 查询至少有一门课与 学号为01的同学 所学相同的同学的信息
方法1(自写)
SELECT DISTINCT s.`SId`,s.`Sname`
FROM student s
JOIN sc c
ON s.`SId` = c.`SId`
WHERE c.`CId` IN
( SELECT cid
FROM sc
WHERE sid = 01)
方法2
SELECT DISTINCT b.*
FROM sc a
INNER JOIN student b
ON a.sid = b.sid
WHERE a.cid IN (SELECT cid FROM sc WHERE sid = 01);
方法3
SELECT c.*
FROM student c
INNER JOIN
(SELECT a.`SId`
FROM sc a
WHERE a.`CId` IN (SELECT cid FROM sc WHERE sid =01 )
GROUP BY a.`SId`) d
ON d.sid = c.`SId`;
9. 查询和01号同学学习的课程完全相同的其他同学的信息
方法1(自写)
没有选01号同学选的以外的课程
选课的数量一样
SELECT * FROM student WHERE sid IN(
SELECT sid
FROM sc
WHERE sid NOT IN (SELECT sid FROM sc WHERE cid NOT IN (SELECT cid FROM sc WHERE sid = 01))
AND sid <> 01
GROUP BY sid
HAVING COUNT(cid)= (SELECT COUNT(cid) FROM sc WHERE sid = 01 )
)
方法2
SELECT *FROM student
WHERE sid IN(
SELECT sid
FROM sc
WHERE sid NOT IN (
SELECT sid FROM sc WHERE cid NOT IN
(SELECT cid FROM sc WHERE sid =01))
AND sid <> 01
GROUP BY sid
HAVING COUNT(cid) = (SELECT COUNT(cid) FROM sc WHERE sid = 01)
)
10.查询没有学过‘张三’老师讲授的任意一门课程的学生姓名
方法1(自写)
SELECT s.sname
FROM student s
WHERE sid NOT IN (
SELECT sid
FROM sc
INNER JOIN course c ON sc.`CId` = c.`CId`
INNER JOIN teacher t ON t.`TId`= c.`TId`
WHERE t.`Tname`='张三'
)
方法2
SELECT sname,sid
FROM student
WHERE sid NOT IN (
SELECT a.sid
FROM sc a
LEFT JOIN course b
ON a.cid = b.cid
LEFT JOIN teacher c
ON b.tid = c.tid
LEFT JOIN student d
ON a.sid = d.sid
WHERE c.tname = '张三'
)
11. 查询两门及其以上不及格课程的同学的学号,姓名及平均成绩
方法1(自写)
SELECT s.sid,s.sname,a.avg_score
FROM student s
JOIN (
SELECT sid,AVG(score) AS avg_score
FROM sc
WHERE score<60
GROUP BY sid
HAVING (COUNT(score<60))>=2
) a
ON a.sid = s.sid;
方法2
step 1.求平均成绩
SELECT sid, AVG(score) AS avg_score
FROM sc
GROUP BY sid
step 2.求出有2门以上课程不及格的同学
SELECT sid
FROM sc
WHERE score <60
GROUP BY sid
HAVING COUNT(1)>1;
step 3.在求平均值的时候筛选出我们要的同学
SELECT a.`SId`,b.`Sname`,AVG(a.`score`)
FROM sc a
LEFT JOIN student b
ON a.sid = b.`SId`
INNER JOIN (
SELECT sid
FROM sc
WHERE score <60
GROUP BY sid
HAVING COUNT(1)>1
) AS c
ON a.sid = c.sid
GROUP BY a.sid
12. 检索 01 课程分数小于60,按分数降序排列的学生信息
方法1(自写)
SELECT *
FROM student s
INNER JOIN sc
ON sc.`SId` = s.sid
WHERE sc.`CId` = 01
AND score < 60
ORDER BY score DESC;
方法2
step 1. 筛选01课程分数小于60 的学生sid
SELECT sid
FROM sc
WHERE cid = 01 AND score < 60
step 2. 关联上学生信息,进行分数降序排列
SELECT b.*,a.score
FROM (
SELECT sid,score
FROM sc
WHERE cid = 01 AND score < 60) a
LEFT JOIN student b
ON a.sid = b.sid
ORDER BY a.score DESC;
13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
方法1(自写)
SELECT DISTINCT s.`SId`,b.`Sname`,s.score, a.avg_score
FROM sc s
JOIN (
SELECT sid ,AVG(score) AS avg_score
FROM sc
GROUP BY sid) a
ON a.sid = s.`SId`
JOIN student b
ON b.`SId` = s.`SId`
ORDER BY a.avg_score DESC;
方法2
step 1.求学生的平均成绩
SELECT sid,AVG(score) AS avg_score
FROM sc
GROUP BY sid
step 2. 给每一条学生成绩信息加上平均成绩,然后排序
SELECT a.*,avg_score
FROM sc a
LEFT JOIN (
SELECT sid,AVG(score) AS avg_score
FROM sc
GROUP BY sid) b
ON a.sid = b.sid
ORDER BY avg_score DESC
14. 查询各科成绩最高分,最低分和平均分
以如下形式显示:课程id,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
及格为>=60 ,中等为[70——80),优良为[80-90),优秀为>=90
要求输出课程号和选秀人数,查询结果按照人数降序排列,若人数相同,按课程号升序排列
方法1(自写)
SELECT s.cid,c.`Cname`,COUNT(1), MAX(score),MIN(score),AVG(score),
SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END )/COUNT(1) AS '及格率',
SUM(CASE WHEN score >= 70 AND score < 80 THEN 1 ELSE 0 END )/COUNT(1) AS '中等率',
SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END )/COUNT(1) AS '优良率',
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END )/COUNT(1) AS '优秀率'
FROM sc s
JOIN course c
ON c.cid = s.cid
GROUP BY s.cid
ORDER BY COUNT(1) DESC,s.cid ASC;
方法2
SELECT
sc.cid, c.cname,
MAX(score) AS '最高分',
MIN(score) AS '最低分',
AVG(score) AS '平均分',
COUNT(1) AS '选修人数',
SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END )/COUNT(1) AS '及格率',
SUM(CASE WHEN score >= 70 AND score < 80 THEN 1 ELSE 0 END )/COUNT(1) AS '中等率',
SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END )/COUNT(1) AS '优良率',
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END )/COUNT(1) AS '优秀率'
FROM sc
JOIN course c ON sc.`CId` = c.`CId`
GROUP BY cid
ORDER BY '选修人数' DESC,sc.cid ASC;
15.按各科成绩进行排序,并显示排名,score重复时继续排序
需要用到变量,
select @变量名 := 1 对变量赋初值
使用: select @变量名
方法1(自写)
SELECT sid ,cid,score,
@rank:=@rank+1 AS '排名'
FROM sc, (SELECT @rank := 0) AS t
ORDER BY score DESC;
方法2
SELECT sid ,cid ,score,@rank:= @rank+1 AS '排名'
FROM sc,(SELECT @rank:= 0) AS t
ORDER BY score DESC;
15.1 按各科成绩进行排序,并显示排名,score重复时合并名次
SELECT sid ,cid ,score,
CASE WHEN @score = score THEN @rank
ELSE @rank:= @rank +1 END AS '排名',
@score := score
FROM sc, (SELECT @rank:= 0 ,@score := NULL) AS t
ORDER BY score DESC;
方法2
SELECT sid ,cid ,score,
CASE WHEN @score = score THEN @rank
WHEN @score := score THEN @rank:= @rank +1
END AS '排名'
FROM sc, (SELECT @rank:= 0 ,@score := NULL) AS t
ORDER BY score DESC;
方法3(mysql 8.0以上版本)
SELECT sid,cid,score,
row_number()over(ORDER BY score DESC) AS ranking
FROM sc
ORDER BY score DESC;
SELECT sid cid ,score,
dense_rank()over(ORDER BY score DESC) AS ranking
FROM sc
ORDER BY score DESC;
16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺
自定义变量的方法:
1.@a := 2;
使用:select @a;
2.select @b:=4;
修改相当于重新复制 select @b:=6;
方法1(自写)
SELECT s.`SId`,s.`Sname`,SUM(score),
@rank := @rank +1 AS '排名'
FROM (SELECT @rank := 0) AS rk,student s
LEFT JOIN sc c
ON c.`SId`=s.`SId`
GROUP BY s.`SId`
ORDER BY SUM(score) DESC;
结果不对。。
方法2
step 1 先求学生的总成绩
SELECT sid,SUM(score) AS scos
FROM sc
GROUP BY sid
ORDER BY scos DESC;
step 2 名次排序
SELECT a.*,
@rank :=IF(@score = scos,'',@rank +1) AS rank,
@score := scos
FROM (
SELECT sid,SUM(score) AS scos
FROM sc
GROUP BY sid
ORDER BY scos DESC) a ,
(SELECT @score := NULL,@rank:=0) b
16.1查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
SELECT a.*,
@rank :=IF(@score = scos,@rank,@rank +1) AS rank,
@score := scos
FROM (
SELECT sid,SUM(score) AS scos
FROM sc
GROUP BY sid
ORDER BY scos DESC) a ,
(SELECT @score := NULL,@rank:=0) b
17.统计各科成绩各分数段的人数:课程编号,课程名称,[100,85),[85,70),[70,60),[60,0]以及所占百分比
方法1(自写)
SELECT s.cid,c.cname,COUNT(1),
SUM(CASE WHEN score > 85 AND score <= 100 THEN 1 ELSE 0 END) AS '[100,85)人数',
SUM(CASE WHEN score > 85 AND score <= 100 THEN 1 ELSE 0 END)/COUNT(1) AS '[100,85)占比',
SUM(CASE WHEN score > 70 AND score <= 85 THEN 1 ELSE 0 END) AS '[85,70)人数',
SUM(CASE WHEN score > 70 AND score <= 85 THEN 1 ELSE 0 END)/COUNT(1) AS '[85,70)占比',
SUM(CASE WHEN score > 60 AND score <= 70 THEN 1 ELSE 0 END) AS '[70,60)人数',
SUM(CASE WHEN score > 60 AND score <= 70 THEN 1 ELSE 0 END)/COUNT(1) AS '[70,60)占比',
SUM(CASE WHEN score > 0 AND score <= 60 THEN 1 ELSE 0 END) AS '[60,0)人数',
SUM(CASE WHEN score > 0 AND score <= 60 THEN 1 ELSE 0 END)/COUNT(1) AS '[60,0)占比'
FROM sc s
JOIN course c
ON s.cid = c.cid
GROUP BY s.cid
方法2
step 1 直接进行分组统计
SELECT
cid,COUNT(1),
SUM(CASE WHEN 0<score AND score <=60 THEN 1 ELSE 0 END)/COUNT(1) AS '(0,60]',
SUM(CASE WHEN 60<score AND score <=70 THEN 1 ELSE 0 END)/COUNT(1) AS '(60,70]',
SUM(CASE WHEN 70<score AND score <=85 THEN 1 ELSE 0 END)/COUNT(1) AS '(70,85]',
SUM(CASE WHEN 85<score AND score <=100 THEN 1 ELSE 0 END)/COUNT(1) AS '(85,100]'
FROM sc
GROUP BY cid;
step 2加一个百分号
SELECT
cid,COUNT(1),
CONCAT(SUM(CASE WHEN 0<score AND score <=60 THEN 1 ELSE 0 END)/COUNT(1)*100,'%') AS '(0,60]',
CONCAT(SUM(CASE WHEN 60<score AND score <=70 THEN 1 ELSE 0 END)/COUNT(1)*100,'%') AS '(60,70]',
CONCAT(SUM(CASE WHEN 70<score AND score <=85 THEN 1 ELSE 0 END)/COUNT(1)*100,'%') AS '(70,85]',
CONCAT(SUM(CASE WHEN 85<score AND score <=100 THEN 1 ELSE 0 END)/COUNT(1)*100,'%') AS '(85,100]'
FROM sc
GROUP BY cid;
18.查询各科成绩前三名的记录
方法1(自写)
可否用limit ?
```sql
SELECT s.`SId`,s.`Sname`,sc.`score`
FROM sc
JOIN student s
ON sc.`SId` = s.`SId`
GROUP BY sc.`CId`
ORDER BY score
修改后:
```sql
SELECT s.`SId`,s.`Sname`,a.`CId`,a.`score`
FROM sc a
JOIN student s
ON a.`SId` = s.`SId`
WHERE (SELECT COUNT(1)
FROM sc b
WHERE a.cid = b.cid
AND b.score > a.score)<3
ORDER BY a.cid DESC,a.score DESC;
方法2
思路:前三名转化为若大于此成绩的数量少于3即为前三名
SELECT a.*
FROM sc a
WHERE ( SELECT COUNT(1)
FROM sc b
WHERE b.cid = a.cid AND b.`score`>a.score
)< 3
ORDER BY cid DESC,score DESC;
19.查询每门课程被选修的学生数
方法1(自写)
SELECT cid,COUNT(1)AS '选修人数'
FROM sc
GROUP BY cid;
方法2
SELECT cid,COUNT(1) AS cons
FROM sc
GROUP BY cid;
20.查询出只选修两门课的学生学号和姓名
方法1(自写)
SELECT s.`SId`,s.`Sname`
FROM student s
JOIN sc c
ON s.`SId` = c.`SId`
GROUP BY s.`SId`
HAVING COUNT(score)=2
方法2
SELECT a.sid,b.sname,COUNT(1) AS '选修课数'
FROM sc a
INNER JOIN student b
ON a.sid = b.sid
GROUP BY a.sid,b.sname
HAVING COUNT(1) = 2;
21.查询男生、女生人数
方法1(自写)
SELECT ssex,COUNT(1)
FROM student
GROUP BY ssex;
方法2
SELECT ssex,COUNT(1) AS cons
FROM student
GROUP BY ssex;
22. 查询名字中含有‘风’字的学生信息
方法1(自写)
SELECT *
FROM student
WHERE sname LIKE '%风%';
方法2
SELECT *
FROM student
WHERE sname LIKE '%风%';
23.查询同名同性别学生名单,并统计同名同性别人数
方法1(自写)
SELECT a.*,b.*,COUNT(1)
FROM student a
INNER JOIN student b
ON a.`Sname` = b.`Sname`
WHERE a.`Ssex` = b.`Ssex`
AND a.`SId` <> b.`SId`
方法2
SELECT a.sname,a.`Ssex`,COUNT(1) AS cons
FROM student a
INNER JOIN student b
ON a.`Sname` = b.`Sname` AND a.`Ssex` = b.`Ssex` AND a.`SId` != b.`SId`;
GROUP BY a.sname ,a.ssex;
24.查询1990年出生的学生名单
方法1(自写)
SELECT *
FROM student
WHERE YEAR(`Sage`) = 1990;
方法2
SELECT YEAR('2000-02-01')
SELECT YEAR('2000/02/01')
SELECT *
FROM student
WHERE YEAR(`Sage`) = 1990;
25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按照课程编号升学排列
SELECT cid,AVG(score) AS '平均成绩'
FROM sc
GROUP BY cid
ORDER BY AVG(score) DESC,cid ASC;
方法2
SELECT cid,AVG(score) AS avg_score
FROM sc
GROUP BY cid
ORDER BY avg_score DESC,cid ASC;
26. 查询平均成绩大于等于85的所有学生的学号,姓名和平均成绩
方法1(自写)
SELECT s.`SId`,s.`Sname`,AVG(score) AS '平均成绩'
FROM sc c
INNER JOIN student s
ON c.`SId` = s.`SId`
GROUP BY c.`SId`
HAVING AVG(score)>=85;
方法2
step 1 先找出符合要求的sid
SELECT sid,AVG(score) AS avg_score
FROM sc
GROUP BY sid
HAVING AVG(score) >= 85;
step 2 关联学生信息
SELECT b.sname, a.sid, a.avg_score
FROM (
SELECT sid, AVG(score) AS avg_score
FROM sc
GROUP BY sid
HAVING AVG(score) >= 85) a
LEFT JOIN student b
ON a.sid = b.sid;
27.查询课程名字为【数学】,且分数低于60的学生姓名和分数
方法1(自写)
SELECT s.`Sname`,c.`score`
FROM student s
JOIN sc c ON s.`SId` = c.`SId`
JOIN course co ON co.`CId` = c.`CId`
WHERE co.`Cname` = '数学' AND c.`score`<60;
方法2
step 1 先查询数学的课程cid
SELECT cid FROM course WHERE cname = '数学'
step 2 求分数低于60的成绩记录
SELECT a.sid,cid,b.sname,b.ssex,a.score
FROM sc a
LEFT JOIN student b
ON a.sid = b.sid
WHERE cid = (SELECT cid FROM course WHERE cname = '数学' )
AND score < 60;
28.查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
方法1(自写)
SELECT DISTINCT s.sid,s.`Sname`,c.`CId`,c.`score`
FROM student s
LEFT JOIN sc c
ON s.`SId` = c.`sId`
方法2
SELECT *
FROM student a
LEFT JOIN sc b
ON a.sid = b.`SId`
29.查询任何一门课程成绩在70分以上的姓名、课程名称和分数
方法1(自写)
SELECT s.`Sname`,co.`Cname`,c.`score`
FROM student s
JOIN sc c ON c.`SId` = s.`SId`
JOIN course co ON co.`CId` = c.`CId`
HAVING c.`score` > 70;
方法2
step 1 先找出成绩大于70分的成绩记录,sid
SELECT *
FROM sc a
LEFT JOIN course c
ON a.`CId` = c.`CId`
WHERE a.`score`>70
step 2 和学生表进行关联得到学生信息
SELECT a.`score`,s.sname,c.`Cname`
FROM sc a
LEFT JOIN course c
ON a.`CId` = c.`CId`
LEFT JOIN student s
ON a.`SId` = s.sid
WHERE a.`score`>70 ;
##30.查询存在不及格的课程
方法1(自写)
SELECT *
FROM sc s
JOIN course c
ON s.`CId` = c.`CId`
WHERE s.`score`<60
方法2
step 1 筛选出小于60分的成绩记录
SELECT * FROM sc WHERE score < 60
tep 2 去重得到cid,如果需要课程信息还可以和course关联
SELECT a.*
FROM course a
WHERE a.cid IN (SELECT cid FROM sc WHERE score < 60)
31.查询课程编号为01 且课程成绩在80分以上的学生的学号和姓名
方法1(自写)
SELECT *
FROM sc c
LEFT JOIN student s
ON s.sid = c.sid
WHERE c.`CId` = 01
AND c.score > 80;
方法2
SELECT a.sid,a.sname,b.score,b.cid
FROM student a
INNER JOIN sc b
ON a.sid = b.sid
WHERE b.cid = 01
AND b.score>80;
32.求每门课程的学生人数
方法1(自写)
SELECT c.*,COUNT(1) AS 学生人数
FROM sc s
JOIN course c
ON s.`CId` = c.`CId`
GROUP BY s.`CId`;
方法2
SELECT cid,COUNT(1) AS cons
FROM sc
GROUP BY cid;
33.假设成绩不重复,查询选修张三老师所授课程的学生中,成绩最高的学生的信息及其成绩
方法1(自写)
SELECT s.*,MAX(c.`score`)
FROM student s
JOIN sc c ON c.`SId` = s.`SId`
JOIN course co ON co.`CId` = c.`CId`
JOIN teacher t ON t.`TId` = co.`TId`
WHERE t.`Tname` ='张三';
方法2
SELECT *
FROM sc a
LEFT JOIN student b
ON a.`SId` = b.`SId`
LEFT JOIN course c
ON c.`CId` = a.`CId`
LEFT JOIN teacher d
ON d.`TId` = c.`TId`
WHERE d.`Tname` = '张三'
ORDER BY a.score DESC
LIMIT 1;
34.假设成绩有重复的情况下,查询张三老师授课的学生中,成绩最高的学生信息及其成绩
方法1(自写)
SELECT s.`SId`,s.`Sname`,a.`score`
FROM sc a
JOIN (
SELECT s.`SId`,c.`CId`,MAX(c.`score`) AS max_score
FROM student s
JOIN sc c ON c.`SId` = s.`SId`
JOIN course co ON co.`CId` = c.`CId`
JOIN teacher t ON t.`TId` = co.`TId`
WHERE t.`Tname` ='张三') b
ON a.`CId` = b.cid
JOIN student s ON a.sid = s.`SId`
WHERE a.`score` = b.max_score
方法2
SELECT *
FROM (
SELECT
a.*,
CASE WHEN @score = score THEN @rank
WHEN @score:= score THEN @rank:=@rank+1 END AS rn
FROM (
SELECT a.sid,a.`score`,b.`Sname`,c.`CId`,d.tname
FROM sc a
LEFT JOIN student b
ON a.`SId` = b.`SId`
LEFT JOIN course c
ON c.`CId` = a.`CId`
LEFT JOIN teacher d
ON d.`TId` = c.`TId`
WHERE d.`Tname` = '张三') a,(SELECT @score := NULL,@rank:=0) t
ORDER BY a.score DESC ) s
WHERE s.rn = 1;
35.查询不同课程成绩相同的学生的学生编号,课程编号,学生成绩
方法1(自写)
SELECT a.*
FROM sc a
INNER JOIN sc b
ON a.`SId` = b.`SId`
WHERE a.`CId` <> b.`CId`
AND a.`score` = b.`score`
方法2
SELECT a.sid,a.`CId`,a.`score`
FROM sc a
INNER JOIN sc b
ON a.`SId` = b.`SId`
WHERE a.`CId` != b.`CId`
AND a.`score` = b.`score`
GROUP BY a.sid,a.`CId`
36.查询每门课成绩最好的前两名
方法1(自写)
SELECT a.cid,a.`score`,a.rank
FROM (SELECT *,
@rank:=IF(@coid= cid,IF(@score=score,@rank,@rank+1),1) AS rank,
@score:=score,
@coid:=cid
FROM sc,(SELECT @rank:=0,@score:= NULL,@coid=NULL ) AS t
ORDER BY cid,score DESC) a
WHERE a.rank<3;
方法2
SELECT *
FROM (
SELECT sc.*,
@rank:=IF(@cid=cid,IF(@sco=score,@rank,@rank+1),1) AS rank,
@sco:=score,
@cid:=cid
FROM sc,(SELECT @sco:=NULL,@rank:=0,@cid:=NULL) b
ORDER BY cid, score DESC) a
WHERE rank<3;
37.统计每门课程的学生选修人数(超过5人的课程才统计)
方法1(自写)
SELECT cid,COUNT(1) AS cons
FROM sc
GROUP BY cid
HAVING COUNT(1)>5;
方法2
SELECT cid,COUNT(1) AS cons
FROM sc
GROUP BY cid
HAVING COUNT(1)>5;
38.检索至少选修两门课程的学生学号
方法1(自写)
SELECT sid,COUNT(1) AS '选修课数'
FROM sc
GROUP BY sid
HAVING COUNT(1)>1;
方法2
SELECT sid,COUNT(1) AS cons
FROM sc
GROUP BY sid
HAVING COUNT(1)>=2;
39.查询选修了全部课程的学生信息
方法1(自写)
SELECT sid,COUNT(1)
FROM sc
GROUP BY sid
HAVING COUNT(1)=
(
SELECT MAX(cons) AS max_cons
FROM (
SELECT sid,COUNT(1) AS cons
FROM sc
GROUP BY sid
HAVING COUNT(1) ) a)
方法2
SELECT *,COUNT(1)
FROM sc
GROUP BY sid
HAVING COUNT(1) = (SELECT COUNT(1)FROM course);
方法3
SELECT a.*
FROM student a
WHERE (SELECT COUNT(1) FROM sc b WHERE a.`SId` = b.`SId`) = (SELECT COUNT(1) FROM course)
40.查询各学生的年龄,只按年份来算
方法1(自写)
SELECT *,
YEAR(NOW())-YEAR(`Sage`) AS age
FROM student
方法2
SELECT *,
YEAR(CURDATE())-YEAR(sage) AS age
FROM student;
41.按照出生日期来算年龄,当前月日<出生年月的月日则年龄减一
方法1(自写)
SELECT *,
TIMESTAMPDIFF(YEAR,`Sage`,NOW()) AS age
FROM student
方法2
–timestampdiff 日期相减函数
SELECT TIMESTAMPDIFF(YEAR,'2019/07/01',NOW())
SELECT TIMESTAMPDIFF(DAY,'2019/07/01',NOW())
SELECT TIMESTAMPDIFF(HOUR,'2019/07/01 12:00:00',NOW())
具体:
SELECT *,
TIMESTAMPDIFF(YEAR,`Sage`,NOW()) AS age
FROM student
42.查询本周过生日的学生
方法1(自写)
SELECT *,
ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR) AS 换算成今年的日期,
DATE_SUB(CURDATE(),INTERVAL(WEEKDAY(NOW()))DAY) AS 周一日期,
DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW())))DAY) AS 周末日期
FROM student
WHERE DATEDIFF(ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR),DATE_SUB(CURDATE(),INTERVAL(WEEKDAY(NOW()))DAY))>=0
AND DATEDIFF(DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW())))DAY),ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR)) >=0;
以当前日期为20201201进行验证:
SELECT *,
ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR) 周末,
ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR)AS 今年的日期,
DATEDIFF(ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR),DATE_SUB('20201201',INTERVAL(WEEKDAY('20201201'))DAY)) 减去周一,
DATEDIFF(DATE_ADD('20201201',INTERVAL(6-(WEEKDAY('20201201')))DAY),ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR)) 周末减去
FROM student
WHERE DATEDIFF(ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR),DATE_SUB('20201201',INTERVAL(WEEKDAY('20201201'))DAY))>=0
AND DATEDIFF(DATE_ADD('20201201',INTERVAL(6-(WEEKDAY('20201201')))DAY),ADDDATE(`Sage`,INTERVAL (YEAR('20201201')-YEAR(`Sage`)) YEAR)) >=0
方法2
WEEK 函数的使用
SELECT WEEK(NOW())
具体:
SELECT *,
WEEK(sage),
WEEK(NOW())
FROM student
WHERE WEEK(sage) = WEEK('2020/07/02');
感觉有问题,当年的第几周不一定是现在的第几个周
43.查询下周过生日的学生
方法1(自写)
SELECT *,
ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR) AS 换算成今年的日期,
DATE_ADD(CURDATE(),INTERVAL(7-WEEKDAY(NOW()))DAY) AS 下周一日期,
DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW()))+7)DAY) AS 下周末日期
FROM student
WHERE DATEDIFF(ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR),DATE_ADD(CURDATE(),INTERVAL(7-WEEKDAY(NOW()))DAY))>=0
AND DATEDIFF(DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW()))+7)DAY),ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR)) >=0;
方法2
SELECT *,
WEEK(sage),
WEEK(NOW())
FROM student
WHERE WEEK(sage) = WEEK('2020/11/22')+1;
有问题的答案。。。
44.查询本月过生日的学生
方法1(自写)
SELECT *
FROM student
WHERE MONTH(NOW()) = MONTH(`Sage`)
方法2
SELECT *
FROM student
WHERE MONTH(sage)=MONTH(NOW())
45.查询下月过生日的学生
方法1(自写)
SELECT *
FROM student
WHERE MONTH(NOW())+1 = MONTH(`Sage`)
01’)-YEAR(Sage
)) YEAR)) >=0
方法2
WEEK 函数的使用
SELECT WEEK(NOW())
具体:
SELECT *,
WEEK(sage),
WEEK(NOW())
FROM student
WHERE WEEK(sage) = WEEK('2020/07/02');
感觉有问题,当年的第几周不一定是现在的第几个周
43.查询下周过生日的学生
方法1(自写)
SELECT *,
ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR) AS 换算成今年的日期,
DATE_ADD(CURDATE(),INTERVAL(7-WEEKDAY(NOW()))DAY) AS 下周一日期,
DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW()))+7)DAY) AS 下周末日期
FROM student
WHERE DATEDIFF(ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR),DATE_ADD(CURDATE(),INTERVAL(7-WEEKDAY(NOW()))DAY))>=0
AND DATEDIFF(DATE_ADD(CURDATE(),INTERVAL(6-(WEEKDAY(NOW()))+7)DAY),ADDDATE(`Sage`,INTERVAL (YEAR(NOW())-YEAR(`Sage`)) YEAR)) >=0;
方法2
SELECT *,
WEEK(sage),
WEEK(NOW())
FROM student
WHERE WEEK(sage) = WEEK('2020/11/22')+1;
有问题的答案。。。
44.查询本月过生日的学生
方法1(自写)
SELECT *
FROM student
WHERE MONTH(NOW()) = MONTH(`Sage`)
方法2
SELECT *
FROM student
WHERE MONTH(sage)=MONTH(NOW())
45.查询下月过生日的学生
方法1(自写)
SELECT *
FROM student
WHERE MONTH(NOW())+1 = MONTH(`Sage`)