mysql45 练习答案

mysql45 练习答案

记录一下自己对题目的理解思路还有做法
– mysql45
练习数据
数据表
–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 分数

创建测试数据
学生表 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-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('09' , '张三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2017-12-30' , '女');
insert into Student values('12' , '赵六' , '2017-01-01' , '女');
insert into Student values('13' , '孙七' , '2018-01-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' , '数学' , '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 "课程成绩高的学生的信息及课程分数

SELECT *
FROM
sc a LEFT JOIN student stu
ON a.sid = stu.sid
INNER JOIN sc b
ON a.sid = b.sid AND a.cid = 01 AND b.cid = 02
WHERE a.score > b.score;

– 1.1 查询同时存在" 01 “课程和” 02 "课程的情况

SELECT *
FROM sc a INNER JOIN sc b
ON a.SId = b.SId AND a.CId = 01 AND b.CId = 02;

– 1.2查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )

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 "课程的情况

SELECT *
FROM sc a
LEFT JOIN sc b 
ON a.SId = b.SId and b.CId = 01
WHERE a.CId = 02 AND b.CId IS NULL;

– 2.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
– 问题:为什么这里的group by 的having 条件查询,可以直接使用 s_avg 别名?

SELECT stu.SId,stu.Sname,avg(a.score) s_avg
FROM student stu INNER JOIN sc a
ON stu.SId = a.SId
GROUP BY stu.SId
HAVING s_avg >= 60;
-- 答:因为sql语句执行顺序:先执行select,再执行having

– 3.查询在 SC 表存在成绩的学生信息

SELECT DISTINCT stu.*
FROM sc a LEFT JOIN student stu
on a.SId = stu.SId;

– 4.查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为null)

SELECT a.sid,a.sname,COUNT(b.CId),SUM(b.score)
FROM student a LEFT JOIN sc b
ON a.sid = b.SId
GROUP BY a.sid;

– 4.1 查有成绩的学生信息

SELECT a.sid,a.sname,COUNT(b.CId),SUM(b.score)
FROM student a INNER JOIN sc b
ON a.sid = b.SId
GROUP BY a.sid;

– 5.查询「李」姓老师的数量

SELECT COUNT(1)
FROM teacher
WHERE tname LIKE '李%';

– 6.查询学过「张三」老师授课的同学的信息

-- a、查询张三老师授课的课程编号
SELECT cid
FROM course
WHERE tid = (
SELECT tid FROM teacher WHERE tname = '张三');
-- b、查询学过「张三」老师授课的同学的信息
SELECT b.*
FROM sc a INNER JOIN student b
ON a.SId = b.SId
WHERE a.CId = (SELECT cid FROM course
 WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三'));

– 7.查询没有学全所有课程的同学的信息

SELECT a.*
FROM student a LEFT JOIN sc b
ON a.SId = b.SId 
GROUP BY a.SId
HAVING COUNT(b.CId) < (select count(cid) from course);

– 8.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息

-- a、查询01同学学的课程id
SELECT cid
FROM sc
WHERE sid = 01
--  b、查询学过01同学课程的同学注意去重
SELECT DISTINCT a.*
FROM student a LEFT JOIN sc b
ON a.sid = b.sid
WHERE b.cid IN (SELECT cid FROM sc WHERE sid = 01);

– 9.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息

-- 找到与01同学课程不同的同学
SELECT DISTINCT sid
FROM sc
where cid NOT IN (SELECT cidFROM sc WHERE sid = 01);
	
-- 排除以上同学,并且限制课程总数
SELECT a.*
FROM student a LEFT JOIN sc b
ON a.SId = b.SId 
WHERE a.SId NOT IN (SELECT DISTINCT sid FROM sc WHERE cid NOT IN 
(SELECT cid FROM sc WHERE sid = 01))
AND a.SId != 01
GROUP BY a.sid
HAVING COUNT(b.CId) = (SELECT COUNT(cid) FROM sc WHERE sid = 01);

– 10.查询没学过"张三"老师讲授的任一门课程的学生姓名

-- 查询张三老师的授课id
SELECT cid
FROM course
WHERE tid = (
SELECT tid FROM teacher WHERE tname = '张三');
-- 查询上过张三老师课程的学生id
SELECT sid
FROM cs 
WHERE cid IN (SELECT cid
	FROM course
	WHERE tid = (
	SELECT tid FROM teacher WHERE tname = '张三'));
	
-- 排除以上学生
SELECT sname
FROM student
WHERE sid NOT IN (SELECT sid
FROM sc 
WHERE cid IN (SELECT cid
	FROM course
	WHERE tid = (
	SELECT tid FROM teacher WHERE tname = '张三')));

– 11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

SELECT a.sid,a.Sname,avg(b.score)
FROM student a LEFT JOIN sc b
ON a.SId = b.SId
WHERE b.score < 60
GROUP BY sid
HAVING COUNT(1) >= 2;

– 12、检索" 01 "课程分数小于 60,按分数降序排列的学生信息

SELECT b.*
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.CId = 01
AND a.score < 60
ORDER BY a.score DESC;

– 13、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

-- 平均成绩
SELECT SId,avg(score) avg_stu
FROM sc 
GROUP BY SId;
-- 表连接
SELECT a.SId,b.cid,b.score,avg_stu
FROM student a LEFT JOIN sc b
ON a.SId = b.SId
LEFT JOIN (SELECT SId,avg(score) avg_stu FROM sc GROUP BY SId) c
ON a.SId = c.SId
GROUP BY a.SId,b.cid
ORDER BY avg_stu DESC;
-- 要关联上student表,题目要求所有学生

– 14、查询各科成绩最高分、最低分和平均分: 以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT
	a.CId 课程ID,
	b.Cname 课程名称,
	COUNT( a.SId ) 选修人数,
	MAX( a.score ) 最高分,
	MIN( a.score ) 最低分,
	AVG( a.score ) 平均分,
	SUM(
	IF
	( a.score >= 60, 1, 0 ))/ COUNT( a.SId ) 及格率,
	SUM(
	IF
	( a.score >= 70 AND a.score < 80, 1, 0 ))/ COUNT( a.SId ) 中等率,
	SUM(
	IF
	( a.score >= 80 AND a.score <= 90, 1, 0 ))/ COUNT( a.SId ) 优良率,
	SUM(
	IF
	( a.score >= 90, 1, 0 ))/ COUNT( a.SId ) 优秀率 
FROM
	sc a
	LEFT JOIN course b ON a.CId = b.CId 
GROUP BY
	a.CId 
ORDER BY
	COUNT( a.SId ) DESC,
	a.CId;

– 15、按各科成绩进行排序,并显示排名, Score 重复时也继续排名

-- 对题目的理解:先按学科分组分数相同时,排名相同,下一个分数的排名为前面的总人数+1
SELECT a.CId,a.SId,a.score,COUNT(b.score)+1 rk
FROM sc a LEFT JOIN sc b 
ON a.CId = b.CId AND a.score < b.score
GROUP BY a.CId,a.SId
ORDER BY a.CId,a.score DESC;

法二:使用窗口函数

SELECT
	a.*,
	RANK() over ( PARTITION BY a.CId ORDER BY a.score DESC ) AS score_rank 
FROM
	sc a;

结果:
image-20210312105723443.png
– 15.1 按各科成绩进行排序,并显示排名, Score 重复时合并名次

-- 对题目的理解:分数相同时,排名相同,下一个分数的排名为上一人排名+1
SELECT
	a.CId,
	a.SId,
	a.score,
	COUNT( DISTINCT b.score )+ 1 rk 
FROM
	sc a
	LEFT JOIN sc b ON a.CId = b.CId 
	AND a.score < b.score 
GROUP BY
	a.CId,
	a.SId 
ORDER BY
	a.CId,
	a.score DESC;

法二:使用窗口函数

SELECT
	a.*,
	DENSE_RANK() over ( PARTITION BY a.CId ORDER BY a.score DESC ) AS score_rank 
FROM
	sc a;

结果:
image-20210312110102908.png
– 16、查询学生的总成绩,并进行排名,总分重复时保留名次空缺

--  查询总成绩
SELECT SId,SUM(score) scores
FROM sc
GROUP BY SId;
-- 利用count进行排名
SELECT a.SId,a.scores,COUNT(b.scores)+1
FROM 
(SELECT SId,SUM(score) scores
FROM sc
GROUP BY SId
) a LEFT JOIN 
(SELECT SId,SUM(score) scores
FROM sc
GROUP BY SId
) b 
ON a.scores < b.scores
GROUP BY a.SId
ORDER BY a.scores DESC;

– 16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺

SELECT a.SId,a.scores,COUNT(DISTINCT b.scores)+1
FROM 
(SELECT SId,SUM(score) scores
FROM sc
GROUP BY SId
) a LEFT JOIN 
(SELECT SId,SUM(score) scores
FROM sc
GROUP BY SId
) b 
ON a.scores < b.scores
GROUP BY a.SId
ORDER BY a.scores DESC;

– 17.统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占

SELECT
	a.cid,
	b.Cname,
	concat( COUNT( IF ( 85 <= score AND score <= 100, 1, NULL ))/ COUNT( 1 )* 100, "%" ) AS "[85-100]",
	concat( COUNT( IF ( 70 <= score AND score < 85, 1, NULL ))/ COUNT( 1 )* 100, "%" ) AS "[70-85]",
	concat( COUNT( IF ( 60 <= score AND score < 70, 1, NULL ))/ COUNT( 1 )* 100, "%" ) AS "[60-70]",
	concat( COUNT( IF ( 0 <= score AND score < 60, 1, NULL ))/ COUNT( 1 )* 100, "%" ) AS "[0-60]" 
FROM
	sc a
	INNER JOIN course b ON a.cid = b.cid 
GROUP BY
	cid;

– 18.查询各科成绩前三名的记录

-- 思路:前三名转化为若大于此成绩的数量少于3即为前三名。
SELECT a.CId,a.SId,a.score
FROM sc a
WHERE 
(SELECT COUNT(1) FROM sc b WHERE b.score > a.score AND a.CId = b.CId) < 3
ORDER BY a.CId,a.score DESC;

– 19.查询每门课程被选修的学生数

SELECT CId,COUNT(1)
FROM sc
GROUP BY CId;

– 20.查询出只选修两门课程的学生学号和姓名

SELECT a.SId,b.Sname
FROM sc a LEFT JOIN student b
ON a.SId = b.SId
GROUP BY a.SId
HAVING COUNT(a.CId) = 2;

– 21.查询男生、女生人数

SELECT Ssex,COUNT(1)
FROM student 
GROUP BY Ssex;

– 22、查询名字中含有「风」字的学生信息

SELECT *
FROM student 
WHERE Sname LIKE '%风%';

– 23.查询同名同性学生名单,并统计同名同姓人数

SELECT Sname,COUNT(1)
FROM student 
GROUP BY Sname
HAVING COUNT(1) > 1;

– 22.查询 1990 年出生的学生名单

SELECT * FROM student WHERE YEAR(Sage) = 1990;

– 25.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列

SELECT CId,AVG(score) avg_sco
FROM sc
GROUP BY CId
ORDER BY avg_sco DESC,CId;

– 26.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩

SELECT a.SId,b.Sname,AVG(a.score)
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
GROUP BY a.SId
HAVING AVG(a.score) >= 85;

– 27、查询课程名称为「数学」,且分数低于 60 的学生姓名和分数

SELECT b.Sname,a.score
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.CId = (SELECT CId FROM course WHERE Cname = '数学')
AND a.score < 60;

– 28、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)

SELECT *
FROM student a LEFT JOIN sc b
ON a.SId = b.SId;

– 29、查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数

SELECT b.Sname,a.CId,a.score
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.score > 70;

– 30.查询存在不及格的课程

SELECT DISTINCT a.CId,b.Cname
FROM sc a LEFT JOIN course b
ON a.CId = b.CId
WHERE a.score < 60;

– 31.查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名

SELECT a.SId,b.Sname
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.CId = 01
AND a.score > 80;

– 32.求每门课程的学生人数

SELECT CId,COUNT(1)
FROM sc
GROUP BY CId;

– 33、假设成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

-- 张三老师课程id
-- 查询上过张三老师课程的学生id
SELECT *
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.cid IN 
	(SELECT cid
	FROM course
	WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')
	)
	ORDER BY score DESC
	LIMIT 1;

– 34、假设成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

-- 找到最高分
SELECT MAX(score)
FROM sc 
WHERE cid IN 
	(SELECT cid
	FROM course
	WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')
	);
-- 找成绩为最高分的同学
SELECT *
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
WHERE a.cid IN 
	(SELECT cid FROM course
	WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')
	)
AND
a.score = (SELECT MAX(score) FROM sc  WHERE cid IN 
(SELECT cid FROM course WHERE tid = 
(SELECT tid FROM teacher WHERE tname = '张三'))
);

– 35、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

-- cha'de'shi
SELECT a.SId,a.CId,a.score,b.SId,b.CId
FROM sc a LEFT JOIN sc b
ON a.score = b.score
WHERE a.CId != b.CId;

SELECT a.SId,a.CId,a.score
FROM sc a LEFT JOIN sc b
ON a.score = b.score
WHERE a.CId != b.CId
GROUP BY a.SId,a.CId;

– 36.查询每门功成绩最好的前两名

SELECT a.CId,a.SId,a.score
FROM sc a
WHERE (SELECT COUNT(1) FROM sc b WHERE a.CId = b.CId AND a.score < b.score) < 2
ORDER BY a.CId,a.score DESC;

– 37.统计每门课程的学生选修人数(超过 5 人的课程才统计)

SELECT CId,COUNT(1)
FROM sc
GROUP BY CId
HAVING COUNT(1)>5;

– 38.检索至少选修两门课程的学生学号

SELECT DISTINCT sid
FROM sc
GROUP BY SId
HAVING COUNT(1) >= 2;

– 39、查询选修了全部课程的学生信息

SELECT b.*
FROM sc a LEFT JOIN student b
ON a.SId = b.SId 
GROUP BY a.SId
HAVING COUNT(1) = (SELECT COUNT(1) FROM course);

– 40.查询各学生的年龄,只按年份来算

SELECT 
sid,
YEAR(NOW()) - YEAR(Sage) age
FROM student;

– 41、按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一

SELECT 
sid,
TIMESTAMPDIFF(YEAR,Sage,NOW()) 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(DATE_ADD(NOW(),INTERVAL 1 MONTH));
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值