# 学生表 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' , '女'); insert into Student values('14' , '陈烈' , '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'); insert into Course values('04' , '数学' , '04');
# 教师表 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' , '王天'); insert into Teacher values('04' , '小李子');
# 成绩表 SC create table SC( SId varchar(10), CId varchar(10), score decimal(18,1)); insert into SC values('01' , '01' ,90); insert into SC values('01' , '02' , 90); insert into SC values('01' , '03' , 99); insert into SC values('02' , '01' , 90); insert into SC values('02' , '02' , 60); insert into SC values('02' , '03' , 82); insert into SC values('03' , '01' , 86); insert into SC values('03' , '02' , 80); insert into SC values('03' , '03' , 81); insert into SC values('04' , '01' , 59); insert into SC values('04' , '02' , 30); insert into SC values('04' , '03' , 20); insert into SC values('05' , '01' , 75); insert into SC values('05' , '02' , 87); insert into SC values('06' , '01' , 33); insert into SC values('06' , '03' , 39); insert into SC values('07' , '02' , 90); insert into SC values('07' , '03' , 98); insert into SC values('08' , '01' , 72);
#解决思路:将sc表拆成两个表,代表01和02课程,将3表联合,再设置筛选条件即可(说明,在mysql中不区分大小写) SELECT * FROM student s JOIN sc a ON s.sid=a.sid INNER JOIN sc b ON s.sid=b.sid AND b.cid=01 AND a.cid=02 WHERE a.score>b.score
#解决思路:用课程代码(cid)条件单独筛选出两张表,然后综合条件'同时存在01和02课程(sid)的情况' ,筛选合并出结果 SELECT * FROM (SELECT * FROM SC WHERE cid='01') a INNER JOIN (SELECT * FROM SC WHERE cid='02') b WHERE a.sid=b.sid
#解题思路:使用学生id(sid)相同和 课程cid=02 两个条件连接两张表,并筛选出课程01的数据;此处注意02课程不存在时要为空 所以不能放在where 条件后 SELECT * FROM sc a LEFT JOIN sc b ON a.sid=b.sid AND b.cid='02' WHERE a.cid='01'
#解题思路:筛选出表中哪些学生不存在课程01(即筛选出某些学生不在 有课程01的表中),再用筛选出来的表内联另外一个课程有02 的表 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'
#解题思路:首先注意是平均分,那就是三门合计平均. 选定特定的三个字段,联合一张成绩大于等于60分的表,根据学生id相同再左联一张表 #(右连接会导致许多字段是NULL,因为右外连接是以右表为基础,右表有的数据全部查出来,不管满不满足条件) SELECT a.sid,b.sname,a.avg_score FROM (SELECT sid,AVG(score) AS avg_score FROM sc GROUP BY sid HAVING avg_score>=60) a LEFT JOIN student b ON a.sid=b.sid
#解题思路:sc表中有成绩的sid是重复的即每一个学生不止一门成绩,用student表中sid 存在于成绩表的sc表里面的条件,即可查出结果. SELECT *FROM student WHERE sid IN(SELECT sid FROM sc)
#解题思路:选课总数和总成绩用 count 和sum 函数算出, 用student 表左外连接 sc表, 再以左表中的sid 进行分组; SELECT a.sid,a.sname, COUNT(b.cid) AS 'cidCount', SUM(b.score) AS 'sumScore' FROM student a LEFT JOIN sc b ON a.sid=b.sid GROUP BY a.sid
#解题思路:重点是有成绩,即学生表中的学生sid在成绩表的有成绩的学生当中; SELECT * FROM student WHERE sid IN(SELECT sid FROM sc)
#解题思路:在计算数量时 count要带括号且括号里面有数字,进行匹配时用like语法; COUNT(1)和COUNT(*)作用相同,都是对所有的结果进行count SELECT COUNT(1) FROM Teacher WHERE tname LIKE '李%'
#解题思路:student表联合sc表才知道什么学生上了什么课,拿了什么成绩;sc表联合course表才知道课程的具体名字;course表联合teacher表才知道 哪门科目是哪个老师教的,再加筛选条件,四表连接; SELECT a.* FROM student a LEFT JOIN sc b ON a.sid=b.sid LEFT JOIN Course c ON b.cid=c.cid LEFT JOIN teacher d ON c.tid=d.tid WHERE d.tname='张三峰'
#解题思路: 所有课程即为course的数量,查询每个学生所学课程数量少于此数量的值即可,即sc表中cid的数量小于 course的总数量的同学信息; SELECT * FROM student a LEFT JOIN sc b ON a.sid=b.sid GROUP BY a.sid HAVING COUNT(b.sid) <(SELECT COUNT(*) FROM course)
left join :左连接,返回左表中所有的记录以及右表中连接字段相等的记录。 right join :右连接,返回右表中所有的记录以及左表中连接字段相等的记录。 inner join: 内连接,又叫等值连接,只返回两个表中连接字段相等的行。 #解题思路:所需要的是同学信息,则以student表左联 学生课程sc表,条件为sc表中的cid与'01'学号同学cid相同即可,用DISTINCT来减少重复信息,即满足至少一名同学;(这里用 left join 和inner join 都可) SELECT DISTINCT a.* FROM student a INNER JOIN sc b ON a.sid=b.sid WHERE b.cid IN (SELECT cid FROM sc WHERE sid='01')
#解题思路:双重否定来筛选出有课程不相同的同学:先选出课程与01同学完全不同的学生,再筛选出 不在这一堆里面的同学并且不是01同学本人再在有着相同课程的同学中,用课程数量与01同学相同的条件筛选出最终结果; SELECT b.* FROM (SELECT * FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid NOT IN(SELECT cid FROM sc WHERE sid="01")) AND sid!="01") a LEFT JOIN student b ON a.sid=b.sid GROUP BY b.sid HAVING COUNT(cid)=(SELECT COUNT(cid) FROM sc WHERE sid="01")
#解题思路:四表联合查出张三峰老师所上课程中上过这个课程的学生信息,利用排除法,不在其中的即为没有学过张三峰老师任何一门课程的学生; SELECT sid,sname FROM student WHERE sid NOT IN (SELECT DISTINCT a.sid FROM student a LEFT JOIN sc b ON a.sid=b.sid LEFT JOIN course c ON b.cid=c.cid LEFT JOIN teacher d ON c.tid=d.tid WHERE d.tname='张三峰')
#解题思路:关键条件:sc表中成绩小于60且数量要大于等于2 即大于1; 联合student表,sc表和成绩不及格课程有两门以上的学生id表即可得到答案; SELECT a.sid,a.sname,AVG(b.score) AS avg_score FROM student a LEFT JOIN sc b ON a.sid=b.sid INNER JOIN (SELECT sid FROM sc WHERE score < 60 GROUP BY sid HAVING COUNT(1)>1) c ON b.sid=c.sid GROUP BY a.sid
#解题思路:联表查询,筛选条件为cid为01,score小于60,并按照成绩降序排序即可; SELECT a.* ,b.score FROM Student a LEFT JOIN SC b ON a.sid=b.sid WHERE b.cid='01' AND b.score<60 ORDER BY b.score DESC
#解题思路:主要是平均成绩的查询,因此需要子查询一个关于平均成绩的表,再与sc表关联,按照平均成绩降序即可; 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
以如下形式显示:课程 ID,课程 NAME,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 要求输出课程号和选修人数, 查询结果按人数降序排列,若人数相同,按课程号升序排列
#解题思路:分子表查询,关键在于使用 case when 语句处理 不同课程成绩统计下来的比率,其余字段计算或拼接即可,排序则按照优先级 先后顺序书写; SELECT a.*,b.Cname FROM (SELECT CId,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 GROUP BY CId) a LEFT JOIN Course b ON a.CId=b.CId ORDER BY 选修人数 DESC,CId ASC
#解题思路:不合并名次,即只用取出各科成绩,进行排序再加上排名递增即可. SELECT sid,cid,score,@rank:=@rank+1 AS rk FROM SC,(SELECT @rank:=0) AS t ORDER BY score DESC //合并名次(更具理解度 SELECT a.cid, a.sid, a.score, COUNT(b.score)+1 AS rank FROM sc AS a LEFT JOIN sc AS b ON a.score(19条消息) sql经典50题之--15. 按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺以千的博客-CSDN博客按各科成绩进行排序,并显示排名
15. 1按各科成绩进行排序,并显示排名, Score 重复时合并名次
#解题思路:排序后,逻辑判断@sco的值是否与前一个值相同,若相同名次不变,不同则加1; SELECT *, CASE WHEN (@sco=score) THEN @rank ELSE @rank:=@rank+1 END AS rn, @sco:=score -- 保存上一次的分数 FROM SC ,(SELECT @rank:=0,@sco:=NULL) AS t ORDER BY score DESC16. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺(即相同成绩排名不同)
#解题思路:学生的总成绩用SUM,排名用@rank去绑定数据(按照成绩顺序累加排名即可),从sc表中取学生id和成绩总和,从另一个新表中赋值两个字段:成绩是否相同,排名. SELECT a.*, @rank:=@rank+1 FROM (SELECT sid,SUM(score) AS scos FROM SC GROUP BY sid ORDER BY scos DESC) a, (SELECT @rank:=0) b16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
#解题思路:学生的总成绩用SUM,排名用@rank去绑定数据,用IF去判断是否成绩相同来取决是否保留名次空缺,从sc表中取学生id和成绩总和,从另一个新表中赋值两个字段:成绩是否相同,排名. SELECT a.*,@rank:=IF(@sco=scoall,@rank,@rank+1) AS rank,@sco:=scoall FROM (SELECT sid ,SUM(score) AS scoall FROM sc GROUP BY sid ORDER BY scoall DESC)a, (SELECT @sco:=NULL,@rank:=0) b;17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
#解题思路:要得到课程编号与名称得联sc和course表,计算其人数用sum,计算百分比 再用人数值除总人数[count(1)] SELECT a.cid ,b.cname, SUM(CASE WHEN 0<=score AND score <=60 THEN 1 ELSE 0 END ) AS '[0,60]人数', SUM(CASE WHEN 0<=score AND score <=60 THEN 1 ELSE 0 END )/COUNT(1)*(100) AS '[0,60](%)', SUM(CASE WHEN 6018.查询各科成绩前三名的记录
#解题思路:最重要的是前三名这个数量如何取到,利用where条件,自连接筛选出成绩前三位, b.score>a.score是关键,大于号变小于号则为求倒数3名. SELECT a.* FROM SC a WHERE (SELECT COUNT(1) FROM SC b WHERE a.cid=b.cid AND, b.score>a.score)<3 ORDER BY cid DESC,score DESC19.查询每门课程被选修的学生数
#解题思路:利用sc表,使用count函数即可计算各个课程被多少人选修 SELECT cid,COUNT(cid) AS cid_sum FROM sc GROUP BY cid20.查询出只选修两门课程的学生学号和姓名
#解题思路:关键在于筛选出只选修两门课的学生,利用count方法去计数筛选,然后联接选出学生名字; SELECT a.sid,b.sname FROM (select SID,COUNT(1) AS 选课数量 from SC GROUP BY SID HAVING COUNT(1) =2 ) a left join Student b on a.sid=b.sid21.查询男生、女生人数
#解题思路:重点在于 需要将ssex分组,不然数据只有男生; SELECT ssex,count(1) as 人数 from Student GROUP BY ssex22.查询名字中含有「风」字的学生信息
SELECT * FROM Student WHERE sname like '%风%'23.查询同名同性学生名单,并统计同名人数
#解题思路:按照姓名分组,姓名形同的情况下按照性别分组统计人数,如果统计人数大于等于1,那说明这个人就是同名同性的 SELECT sname,ssex,count(sname) FROM Student GROUP BY sname,ssex HAVING count(sname)>124.查询 1990 年出生的学生名单
SELECT * FROM Student WHERE YEAR(sage)='1990'25.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
#解题思路:数据在sc一张表中就可以取得,之后按照成绩排列就好,记得另起名字方便调用 SELECT cid,AVG(score) AS avg_score FROM SC GROUP BY cid ORDER BY avg_score DESC,cid ASC26.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
#解题思路:主要是大于等于85的数据要用sc表筛选一下,姓名的信息直接外连接student表即可。 SELECT a.sid, b.sname, 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.sid27.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
#解题思路:利用cid在course表中的cname=数学来筛选出课程(用到in)。成绩直接条件 and 即可; SELECT b.sname, a.score FROM SC a LEFT JOIN Student b ON a.sid=b.sid WHERE a.cid IN (SELECT cid FROM Course WHERE cname='数学') AND a.score<6028.查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
#解题思路:注意连接时,左连接以左边为准,左边数据全在,右连接原理与左连接相同; SELECT * FROM Student a LEFT JOIN SC b ON a.sid=b.sid29.查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
#解题思路:连接,筛选值 SELECT b.sname,c.cname,a.score FROM SC a LEFT JOIN Student b ON a.sid=b.sid LEFT JOIN Course c ON a.cid=c.cid WHERE a.score>7030. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
#解题思路:有条件的连表; SELECT a.sid,b.sname FROM (SELECT sid from SC where cid='01' and score>=80) a left JOIN Student b on a.sid=b.sid31.求每门课程的学生人数
select cid, count(1) as con from SC group by cid 32.成绩不重复,查询选修「张三峰」老师所授课程的学生中,成绩最高的学生信息及其成绩
#解题思路:4张表连接起来,按成绩排序降序,取第一条记录,就是成绩最高的;注意:不要用left/right join 连表,因为会保留左/右表的全部数据; SELECT a.*,b.score FROM Student a INNER JOIN SC b ON a.sid=b.sid INNER JOIN Course c ON b.cid=c.cid INNER JOIN Teacher d ON c.tid=d.tid WHERE d.Tname='张三峰' ORDER BY b.score DESC LIMIT 133.成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
#解题思路:关键在于找到最高分数是多少,然后用in来判断即可 SELECT a.*,b.CId,score FROM Student a JOIN SC b ON a.SId = b.SId JOIN Course c ON b.CId = c.CId JOIN Teacher d ON c.TId = d.TId WHERE Tname = '张三峰' AND score IN (SELECT MAX(score) FROM SC JOIN Course ON SC.CId = Course.CId JOIN Teacher ON Course.TId = Teacher.TId WHERE Tname = '张三峰')34.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
#解题思路:是一个学生的不同课程成绩相同,所以可以拿相同的表关联筛选 SELECT DISTINCT a.* FROM sc a JOIN sc b ON a.SId=b.SId WHERE a.score=b.score AND a.CId!=b.CId35.查询每门成绩最好的前两名
#解题思路:自连接,解决排名问题需要用count 来计算A比B成绩小的数据以此来作为排名; SELECT A.CId,A.SId,A.score,COUNT(B.score) +1 AS ranking FROM SC A LEFT JOIN SC B ON A.CId = B.CId AND A.score36.统计每门课程的学生选修人数(超过 7 人(包括7人)的课程才统计)
SELECT cid,COUNT(sid) sidnum FROM sc GROUP BY cid HAVING sidnum >=737.检索至少选修两门课程的学生学号
SELECT sid FROM sc GROUP BY sid HAVING COUNT(cid) >=238.查询选修了全部课程的学生信息
#解题思路:主要找出课程数量,然后去用此作为条件筛选;用student表和sc表联合来取得不同学生的cid数量,然后having 过滤 SELECT a.* FROM student a INNER JOIN sc b ON a.sid=b.sid GROUP BY a.sid HAVING COUNT(cid)=(SELECT COUNT(cid) FROM course)39.查询各学生的年龄,只按年份来算
#解题思路;主要在于年龄如何换算;关键用法,year取字符串中年的部分 SELECT Sname,Sage, YEAR(NOW())-YEAR(Sage) AS 年龄 FROM student40.按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
#解法一:利用case when 来解决不同情况下的年龄加减; SELECT Sname,Sage, case when (DATE_FORMAT(NOW(),'%m-%d')- DATE_FORMAT(Sage,'%m-%d')) <0 then year(now())-year(Sage)+1 else year(now())-year(Sage) end as 年龄 FROM student #解法二:利用timestampDiff SELECT SId,Sname,TIMESTAMPDIFF(YEAR,Sage,NOW()) AS age FROM Student41.查询本周过生日的学生
#解题思路:利用week() 和now()函数 SELECT * FROM student WHERE WEEK(Sage)=WEEK(NOW()); #查询下周过生日的学生 SELECT * FROM student where week(Sage)=week(now())+142.查询本月过生日的学生
SELECT * FROM student WHERE MONTH(Sage)=MONTH(NOW()) #查询下个月过生日的 SELECT * FROM student WHERE MONTH(Sage)=MONTH(NOW())+1