【学习笔记】MySQL经典45题

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`)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二天 1、查询客户表,统计每个机构2000年之前开户数、2000~2005开户数(含头不含尾)、2005~2010开户数(含头不含尾)、2010之后开户数 展示字段:机构号、2000年之前开户数、2000~2005年开户数、2005~2010年开户数、2010年之后开户数 2、查询客户表,按年份统计,每年、每个机构开户数占全年开户数的占比 展示字段:年份、机构号、开户数、开户占比百分比(百分比) 3、统计所有客户的客户号、存款账户数、2011.12.31日的存款余额、2011.12存款月日均、贷款账户数、2011.12.31日的贷款余额、2011.12贷款月日均 备注:null置为0 第三天 1、统计所有客户的2011.12.31日的存款余额、存款比上日余额、存款比上月余额、、存款比上年余额 备注:存款比上日余额 = 2011.12.31日的存款余额-2011.12.30日的存款余额 存款比上月余额 = 2011.12.31日的存款余额-2011.11.30日的存款余额 存款比上年余额 = 2011.12.31日的存款余额-2010.12.31日的存款余额 只有2011.12.31这个日期可以写死,其他日期要通过2011.12.31这个日期来生成。 2、统计所有2011年存款年日均大于100的客户号、客户名称、存款账户数、2011年年日均 第四天 1、统计所有2011年存款年日均和2011年贷款年日均都大于100的客户号、存款账户数、2011年存款年日均、贷款账户数、2011年贷款年日均 2、统计所有客户的客户号、 存款标志(有存款账户的客户置为1、没存款账户的客户置为0)、 贷款标志(有贷款借据的客户置为1、没贷款借据的客户置为0)、 存款质量分类(2011年存款年日均>=10000置为优质、2011年存款年日均>=1000<10000 置为良好、2011年存款年日均=10000置为优质、2011年贷款年日均>=1000<10000 置为良好、2011年贷款年日均<1000置为普通)、 2011年贷款年日均 第五天 1、根据《事件表.xlsx》来建表,然后将excel中的数据导入到目标表中 2、根据客户表、存款信息表、事件表,统计每个客户2017年的客户号、 交易账户数(客户下有多少个账户有交易就是多少)、 当年有交易的天数(如果2017年有5天有过交易,则有交易天数为5)、 当年有交易总月数(如果2017的1、3、5月有交易,则有交易总月数为3)、 最大的月交易总金额(按月统计交易金额,存放最大的月交易金额)、 最大月交易金额的月份(按月统计交易金额,存放交易金额最大的月份)、 年总交易金额、 年交易金额排名(按客户排名,如果总交易金额为0,则不参与排名,排名置为9999)、 年总手续费、 年总手续费排名(按客户排名,如果总手续费为0,则不参与排名,排名置为9999)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值