zoukankan      html  css  js  c++  java
  • MySQL(三)——MySQL45题

    iwehdio的博客园:https://www.cnblogs.com/iwehdio/

    1、表结构分析

    • 共有四张表,学生表Student、课程表Course、教师表Teacher和成绩表SC。
    • 学生表Student:
      • SId:学生编号。
      • Sname:学生姓名。
      • Sage:出生年月。
      • Ssex:学生性别。
    • 课程表Course:
      • CId:课程编号。
      • Cname:课程名称。
      • TId:教师编号。
    • 教师表Teacher:
      • TId:教师编号。
      • Tname:教师姓名。
    • 成绩表SC:
      • SId:学生编号。
      • CId:课程编号。
      • score:课程分数。
    • 表之间的关系:
      • 学生表和成绩表之间,通过学生编号联系。
      • 课程表和教师表之间,通过教师编号联系。
      • 课程表与成绩表之间,通过课程编号联系。

    2、1~5题

    • 第1题:

      • 题目:

        • 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数。
        • 查询同时存在” 01 “课程和” 02 “课程的情况。
        • 查询存在” 01 “课程但可能不存在” 02 “课程的情况(不存在时显示为 null )。
        • 查询不存在” 01 “课程但存在” 02 “课程的情况。
      • 用到的表:学生表、成绩表。

      • 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数:

        • 因为需要同时显示学生信息和两门课程的分数,因此需要用两次内连接,将两门课程分数的列添加。
        • 两次内连接的连接条件都是学生编号,第一次连接01课程,第二次连接02课程。
        • 最后的筛选条件是01课程比02课程乘积高。
        SELECT a.*,b.`score` '01_score',c.`score` '02_score'
        FROM Student a
        INNER JOIN sc b
        ON a.`SId`=b.`SId` AND b.`CId`='01'
        
        INNER JOIN sc c
        ON a.`SId`=c.`SId` AND c.`CId`='02'
        
        WHERE b.`score` > c.`score`;
        
      • 查询同时存在” 01 “课程和” 02 “课程的情况:

        • 其实就相当于上题中不加筛选条件。
        SELECT a.*,b.`score` '01_score',c.`score` '02_score'
        FROM Student a
        INNER JOIN sc b
        ON a.`SId`=b.`SId` AND b.`CId`='01'
        
        INNER JOIN sc c
        ON a.`SId`=c.`SId` AND c.`CId`='02';
        
      • 查询存在” 01 “课程但可能不存在” 02 “课程的情况(不存在时显示为 null ):

        • 02课程不存在时显示为null,也就是将第二次的内连接改为左外连接。
        SELECT a.*,b.`score` '01_score',c.`score` '02_score'
        FROM Student a
        INNER JOIN sc b
        ON a.`SId`=b.`SId` AND b.`CId`='01'
        
        LEFT OUTER JOIN sc c
        ON a.`SId`=c.`SId` AND c.`CId`='02';
        
      • 查询不存在” 01 “课程但存在” 02 “课程的情况:

      • 与上题类似,但是注意要先做内连接。

      SELECT a.*,c.`score` '01_score',b.`score` '02_score'
      FROM Student a
      INNER JOIN sc b
      ON a.`SId`=b.`SId` AND b.`CId`='02'
      
      LEFT OUTER JOIN sc c
      ON a.`SId`=c.`SId` AND c.`CId`='01';
      
    • 第2题:

      • 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩。
      • 用到的表:学生表、成绩表。
      • 首先,用子查询查询出学生编号和其对应的平均成绩,并进行筛选大于60。
      • 用子查询的结果与学生表进行内连接。
      SELECT a.`SId`,a.`Sname`,c.avg_sc
      FROM Student a
      INNER JOIN(
      SELECT AVG(b.`score`) avg_sc,b.`SId` SId
      FROM sc b
      GROUP BY b.`SId`
      HAVING avg_sc>60
      ) c ON a.`SId`=c.SId;
      
    • 第3题:

      • 查询在 SC 表存在成绩的学生信息。
      • 用到的表:学生表、成绩表。
      • 将学生表和成绩表进行内连接,然后只显示学生信息并去重。
      SELECT DISTINCT a.*
      FROM Student a
      INNER JOIN sc b
      ON a.`SId`=b.`SId`;
      
    • 第4题:

      • 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )。
      • 先用子查询,分别查出学生编号对应的选课总数和课程总成绩。
      • 因为没有成绩的显示为null,所以用左外连接。
      • 先左外连接,再分组也可以。
      SELECT a.SId,a.Sname,b.c_count,b.c_sum
      FROM Student a
      LEFT OUTER JOIN (
      	SELECT COUNT(*) c_count,SUM(score) c_sum,SId
      	FROM sc
      	GROUP BY SId
      ) b ON a.SId=b.SId;
      --------------------------------------------
      SELECT a.SId,a.Sname,COUNT(*) c_count,SUM(score) c_sum
      FROM Student a
      LEFT OUTER JOIN sc b
      ON a.SId=b.SId
      GROUP BY SId;
      
    • 第5题:

      • 查询「李」姓老师的数量 。
      • 用到的表:教师表。
      SELECT COUNT(*)
      FROM teacher a
      WHERE a.`Tname` LIKE "李%";
      

    3、6~10题

    • 第6题:

      • 查询学过「张三」老师授课的同学的信息 。
      • 用到的表:四张表都要用到。教师表必须由课程表关联,课程表必须由成绩表才能关联到学生表。
      • 学生表用SId关联成绩表,成绩表用CId关联课程表,课程表用TId关联教师表。三次内连接。
      SELECT a.*
      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`='张三';
      
    • 第7题:

      • 查询没有学全所有课程的同学的信息 。
      • 用到的表:学生表,成绩表。
      • 首先查出所有课程的同学的SId,然后以SId不在这些结果中进行筛选。
      SELECT a.*
      FROM student a
      WHERE  a.`SId` NOT IN(
      	SELECT b.`SId`
      	FROM sc b
      	GROUP BY b.SId
      	HAVING COUNT(*)=(
      		SELECT COUNT(*)
      		FROM course
      	)
      );
      
    • 第8题:

      • 查询至少有一门课与学号为” 01 “的同学所学相同的同学的信息 。
      • 用到的表:学生表,成绩表。
      • 先查出学号为01的同学所学的课程。
      • 然后将学生表和成绩表内连接,筛选条件为课程CId在01同学所学的课程中。
      • 最后用distinct对学生信息去重。
      SELECT DISTINCT a.*
      FROM student a
      INNER JOIN sc b
      ON a.`SId`=b.`SId`
      WHERE b.`CId` IN (
      	SELECT d.`CId`
      	FROM student c
      	INNER JOIN sc d
      	ON c.`SId`=d.`SId`
      	WHERE c.`SId`='01' 
      );
      
    • 第9题:

      • 查询和” 01 “号的同学学习的课程完全相同的其他同学的信息 。
      • 用到的表:学生表,成绩表。
      • 在上一题的基础上,先不去重,则剩下的都是选的课在01选的课之中的信息。那么如果剩下的每个同学的信息与01选的课的数量相同,则选的课是完全相同。
      SELECT a.*
      FROM student a
      INNER JOIN sc b
      ON a.`SId`=b.`SId`
      WHERE b.`CId` IN (
      	SELECT d.`CId`
      	FROM student c
      	INNER JOIN sc d
      	ON c.`SId`=d.`SId`
      	WHERE c.`SId`='01' 
      ) GROUP BY a.`SId`
      HAVING COUNT(*)=(
      	SELECT COUNT(*)
      	FROM sc e
      	WHERE e.`SId`='01'
      );
      
    • 第10题:

      • 查询没学过”张三”老师讲授的任一门课程的学生姓名 。
      • 用到的表:四张表都要用到。
      • 首先查出张三讲授的课程编号,看作一列。
      • 将学生表和成绩表内联,然后左外连接张三讲授的课程编号。
      • 最后按学生编号分支,计算左外连接到的课程编号中不为null的个数。个数为0的筛选出来。
      SELECT a.`Sname`
      FROM student a
      INNER JOIN sc b
      ON a.`SId`=b.`SId`
      
      LEFT OUTER JOIN (
      	SELECT d.`CId` c_cid
      	FROM teacher c
      	INNER JOIN course d
      	ON c.`TId`=d.`TId`
      	WHERE c.`Tname`='张三'
      ) e
      ON b.`CId`=e.c_cid
      GROUP BY a.`SId`
      HAVING COUNT(e.c_cid)=0;
      

    4、11~15题

    • 第11题:

      • 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩 。
      • 用到的表:学生表,课程表。
      • 首先子查询查出两门及其以上不及格的学号。
      • 学生表内连接子查询,并且计算出平均分。
      SELECT b.`SId`,b.`Sname`,(
      	SELECT AVG(d.score)
      	FROM sc d
      	WHERE c.a_sid=d.SId
      	GROUP BY d.SId
      ) sc_avg
      FROM student b
      INNER JOIN (
      	SELECT a.`SId` a_sid
      	FROM sc a
      	WHERE a.`score`<60
      	GROUP BY a.`SId`
      	HAVING COUNT(*)>=2
      ) c ON b.`SId`=c.a_sid;
      
    • 第12题:

      • 检索” 01 “课程分数小于 60,按分数降序排列的学生信息。
      • 用到的表:学生表,成绩表。
      • 查出01课程分数小于60的学生编号,然后与学生表内连接,最后排序。
      SELECT a.*,c.score a_score
      FROM student a
      INNER JOIN (
      	SELECT b.`score`,b.`SId`
      	FROM sc b
      	WHERE b.`CId`='01' AND b.`score`<60
      ) c ON a.`SId`=c.SId
      ORDER BY a_score DESC;
      
    • 第13题:

      • 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩。
      • 用到的表:学生表,成绩表。
      • 先计算出所有学生的平均分,然后与成绩表自连接,最后排序。
      SELECT	b.*,c.c_avg
      FROM sc b
      INNER JOIN (
      	SELECT AVG(a.`score`) c_avg,a.`SId`
      	FROM sc a
      	GROUP BY a.`SId`
      ) c ON b.`SId`=c.SId
      ORDER BY c.c_avg DESC;
      
    • 第14题:

      • 查询各科成绩最高分、最低分和平均分:
        • 以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
        • 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
        • 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
      • 用到的表:课程表,学生表,成绩表。
      • 多个子查询左外连接。注意为例避免null出现,需要用ifnull函数,尤其是计算count个数时。
      SELECT a.`CId` 课程ID,a.`Cname` 课程name,IFNULL(b.b_max,-1) 最高分,IFNULL(c.c_min,-1) 最低分,
      	IFNULL(d_avg,-1) 平均分,IFNULL(e_count,0) 选修人数,
      	IFNULL(count_you,0)/IFNULL(e_count,1) 优秀率,
      	IFNULL(count_liang,0)/IFNULL(e_count,1) 良好率,
      	IFNULL(count_zhong,0)/IFNULL(e_count,1) 中等率,
      	IFNULL(count_jige,0)/IFNULL(e_count,1) 及格率
      FROM course a
      LEFT JOIN (
      	SELECT CId,MAX(score) b_max
      	FROM sc
      	GROUP BY CId
      ) b ON a.`CId`=b.CId
      
      LEFT JOIN (
      	SELECT CId,MIN(score) c_min
      	FROM sc
      	GROUP BY CId
      ) c ON a.`CId`=c.CId
      
      LEFT JOIN (
      	SELECT CId,AVG(score) d_avg
      	FROM sc
      	GROUP BY CId
      ) d ON a.`CId`=d.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) e_count
      	FROM sc
      	GROUP BY CId
      ) e ON a.`CId`=e.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_you
      	FROM sc 
      	WHERE score>=90
      	GROUP BY CId
      ) f ON a.`CId`=f.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_liang
      	FROM sc
      	WHERE score<90 AND score>=80
      	GROUP BY CId
      ) g ON a.`CId`=g.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_zhong
      	FROM sc
      	WHERE score<80 AND score>=70
      	GROUP BY CId
      ) h ON a.`CId`=h.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_jige
      	FROM sc
      	WHERE score>=60
      	GROUP BY CId
      ) i ON a.`CId`=i.CId
      ORDER BY e_count,a.`CId`;
      
    • 第15题:

      • 按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺。
      • 用到的表:成绩表。
      • 在select后子查询,名次其实就是在当前科目中,分数比自己低的人数加1。需要注意使用count函数,没有比他小的时候是null。
      • 分数重复就看的是count的是比自己低的人数还是分数数,如果合并需要加distinct。
      SELECT a.`CId`,IFNULL((
      	SELECT COUNT(score)+1
      	FROM sc b
      	WHERE a.`CId`=b.CId AND b.score>a.`score`
      	GROUP BY b.CId
      ),1) number,a.`SId`,a.`score`
      FROM sc a
      ORDER BY CId,number;
      
      
      • 按各科成绩进行排序,并显示排名, Score 重复时合并名次。
      SELECT a.`CId`,IFNULL((
      	SELECT COUNT(DISTINCT score)+1
      	FROM sc b
      	WHERE a.`CId`=b.CId AND b.score>a.`score`
      	GROUP BY b.CId
      ),1) number,a.`SId`,a.`score`
      FROM sc a
      ORDER BY CId,number;
      

    5、16~20题

    • 第16题:

      • 查询学生的总成绩,并进行排名,总分重复时保留名次空缺。
      • 用到的表:成绩表。
      • 与15题类似,只不过这次使用的子表不是成绩表,而是子查询产生的总成绩表。
      SELECT b.*,IFNULL((
      	SELECT COUNT(sum_score)+1
      	FROM (
      		SELECT a.`SId`,SUM(score) sum_score
      		FROM sc a
      		GROUP BY a.`SId`
      	) c
      	WHERE c.sum_score>b.sum_score
      ),1) number
      FROM (
      	SELECT a.`SId`,SUM(score) sum_score
      	FROM sc a
      	GROUP BY a.`SId`
      )b ORDER BY number;
      
      • 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺。
      SELECT b.*,IFNULL((
      	SELECT COUNT(DISTINCT sum_score)+1
      	FROM (
      		SELECT a.`SId`,SUM(score) sum_score
      		FROM sc a
      		GROUP BY a.`SId`
      	) c
      	WHERE c.sum_score>b.sum_score
      ),1) number
      FROM (
      	SELECT a.`SId`,SUM(score) sum_score
      	FROM sc a
      	GROUP BY a.`SId`
      )b ORDER BY number;
      
    • 17题:

      • 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比。
      • 用到的表:课程表,成绩表。
      • 类似14题。
      SELECT a.`CId` 课程ID,a.`Cname` 课程name,
      	IFNULL(count_you,0) `[100-85]`,
      	IFNULL(count_you,0)/IFNULL(e_count,1) `[100-85]%`,
      	IFNULL(count_liang,0) `[85-70]%`,
      	IFNULL(count_liang,0)/IFNULL(e_count,1) `[85-70]`,
      	IFNULL(count_zhong,0) `[70-60]`,
      	IFNULL(count_zhong,0)/IFNULL(e_count,1) `[70-60]%`,
      	IFNULL(count_jige,0) `[60-0]`,
      	IFNULL(count_jige,0)/IFNULL(e_count,1) `[60-0]%`
      FROM course a
      LEFT JOIN (
      	SELECT CId,COUNT(score) e_count
      	FROM sc
      	GROUP BY CId
      ) e ON a.`CId`=e.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_you
      	FROM sc
      	WHERE score<=100 AND score>=85
      	GROUP BY CId
      ) f ON a.`CId`=f.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_liang
      	FROM sc
      	WHERE score<85 AND score>=70
      	GROUP BY CId
      ) g ON a.`CId`=g.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_zhong
      	FROM sc
      	WHERE score<70 AND score>=60
      	GROUP BY CId
      ) h ON a.`CId`=h.CId
      
      LEFT JOIN (
      	SELECT CId,COUNT(score) count_jige
      	FROM sc
      	WHERE score<60 AND score>=0
      	GROUP BY CId
      ) i ON a.`CId`=i.CId
      ORDER BY e_count,a.`CId`;
      
    • 18题:

      • 查询各科成绩前三名的记录。
      • 用到的表:成绩表,课程表。
      • 将前三名转化为低于此分数的人少于3个就是前三名,至于分数相同导致多于3人暂不处理。
      SELECT a.`CId`,a.`SId`,a.`score`
      FROM sc a
      WHERE (
      	SELECT COUNT(*)
      	FROM sc b
      	WHERE a.`CId`=b.`CId` AND a.`score`<b.`score`
      )<3
      ORDER BY CId,score DESC;
      
    • 第19题:

      • 查询每门课程被选修的学生数 。
      • 用到的表:课程表,成绩表。
      SELECT b.`Cname`,c.c_count
      FROM course b
      INNER JOIN (
      	SELECT a.`CId`,COUNT(*) c_count
      	FROM sc a
      	GROUP BY a.`CId`
      ) c ON b.`CId`=c.CId;
      
    • 第20题:

      • 查询出只选修两门课程的学生学号和姓名 。
      • 用到的表:学生表,成绩表。
      • 先子查询出每个同学选修的课程数。
      SELECT b.`SId`,b.`Sname`
      FROM student b
      INNER JOIN (
      	SELECT a.`SId` c_cid,COUNT(*) c_count
      	FROM sc a
      	GROUP BY a.`SId`
      ) c ON b.`SId`=c.c_cid
      WHERE c.c_count=2;
      

    6、21~25题

    • 第21题:

      • 查询男生、女生人数。
      • 用到的表:学生表。
      SELECT	Ssex,COUNT(*)
      FROM student
      GROUP BY Ssex;
      
    • 第22题:

      • 查询名字中含有「风」字的学生信息。
      • 用到的表:学生表。
      SELECT *
      FROM student
      WHERE Sname LIKE "%风%";
      
    • 第23题:

      • 查询同名同性学生名单,并统计同名人数。
      • 用到的表:学生表。
      • 即按姓名性别分组,组中个数大于1的即为有重名的。
      SELECT	*,COUNT(*) s_count
      FROM student
      GROUP BY Sname,Ssex
      HAVING s_count>1;
      
    • 第24题:

      • 查询 1990 年出生的学生名单。
      • 用到的表:学生表。
      SELECT *
      FROM student
      WHERE YEAR(Sage)=1990;
      
    • 第25题:

      • 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列。
      • 用到的表:成绩表。
      SELECT CId,AVG(score) sc_avg
      FROM sc
      GROUP BY CId
      ORDER BY sc_avg DESC,CId;
      

    7、26~30题

    • 第26题:

      • 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩 。
      • 用到的表:学生表,成绩表。
      • 先用子查询查出学生的平均成绩。
      SELECT a.`SId`,a.`Sname`,b.sc_avg
      FROM student a
      INNER JOIN (
      	SELECT SId,AVG(score) sc_avg
      	FROM sc
      	GROUP BY SId
      ) b
      ON a.`SId`=b.`SId`
      WHERE b.sc_avg>85;
      
    • 第27题:

      • 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数 。
      • 用到的表:课程表,学生表,成绩表。
      • 先查出数学课程的成绩。
      SELECT c.`Sname`,d.score
      FROM student c
      INNER JOIN (
      	SELECT a.`SId`,a.`score`
      	FROM sc a
      	INNER JOIN course b
      	ON a.`CId`=b.`CId`
      	WHERE b.`Cname`="数学"
      ) d ON c.`SId`=d.SId
      WHERE d.score<60;
      
    • 第28题:

      • 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)。
      • 用到的表:学生表,课程表,成绩表。
      SELECT a.`Sname`,d.Cname,d.score
      FROM student a
      INNER JOIN (
      	SELECT b.`SId`,c.`Cname`,b.`score`
      	FROM sc b
      	INNER JOIN course c
      	ON b.`CId`=c.`CId`
      ) d ON a.`SId`=d.SId;
      
    • 第29题:

      • 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数。
      • 用到的表:成绩表,学生表,课程表。
      • 两次内连接,第一次连接成绩表和课程表,筛选70分以上后,再与学生表连接。
      SELECT c.`Sname`,d.Cname,d.score
      FROM student c
      INNER JOIN (
      	SELECT a.`CId`,a.`Cname`,b.score,b.SId
      	FROM course a
      	INNER JOIN (
      		SELECT SId,CId,score
      		FROM sc
      		WHERE score>70
      	) b ON a.`CId`=b.CId
      	WHERE b.score>70
      ) d ON c.`SId`=d.SId;
      
    • 第30题:

      • 查询不及格的课程。
      • 用到的表:成绩表,学生表,课程表。
      SELECT b.`Cname`,d.`Sname`,c.score
      FROM course b
      INNER JOIN (
      	SELECT CId,SId,score
      	FROM sc 
      	WHERE score<60
      ) c ON b.`CId`=c.CId
      INNER JOIN student d
      ON c.SId=d.`SId`;
      

    8、31~35题

    • 第31题:

      • 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名。
      • 用到的表:学生表,成绩表。
      SELECT a.`SId`,a.`Sname`,b.score
      FROM student a
      INNER JOIN (
      	SELECT SId,score
      	FROM sc
      	WHERE CId=01 AND score>80
      ) b ON a.`SId`=b.SId;
      
    • 第32题:

      • 求每门课程的学生人数 。
      • 用到的表:成绩表,课程表。
      SELECT a.`Cname`,b.s_count
      FROM course a
      INNER JOIN (
      	SELECT CId,COUNT(*) s_count
      	FROM sc
      	GROUP BY CId
      ) b ON a.`CId`=b.CId;
      
    • 第33题:

      • 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩。
      • 用到的表:四张表都要用到。
      • 先子查询和内连接查出张三所教学生及其成绩,然后用排序取第一个的方式获得最高成绩。
      SELECT f.*,e.score
      FROM (
      	SELECT d.`SId`,d.`score`
      	FROM (
      		SELECT a.`CId`
      		FROM course a
      		INNER JOIN teacher b
      		ON a.`TId`=b.`TId`
      		WHERE b.`Tname`="张三"
      	) c INNER JOIN sc d
      	ON c.CId=d.`CId`
      	ORDER BY d.`score`DESC
      	LIMIT 1
      ) e INNER JOIN student f
      ON e.SId=f.`SId`;
      
    • 第34题:

      • 成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩。
      • 用到的表:四张表都要用到。
      • 就是将之前的选取最高成绩的方式改为,分数等于该科目的最高分。
      SELECT f.*,e.score
      FROM (
      	SELECT d.`SId`,d.`score`
      	FROM (
      		SELECT a.`CId`
      		FROM course a
      		INNER JOIN teacher b
      		ON a.`TId`=b.`TId`
      		WHERE b.`Tname`="张三"
      	) c INNER JOIN sc d
      	ON c.CId=d.`CId`
      	INNER JOIN (
      		SELECT CId,MAX(score) sc_max
      		FROM sc
      		GROUP BY CId
      	) g ON c.CId=g.CId
      	WHERE d.`score`=g.sc_max
      ) e INNER JOIN student f
      ON e.SId=f.`SId`;
      
    • 第35题:

      • 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 。
      • 用到的表:成绩表,学生表。
      SELECT a.SId
      FROM (	
      	SELECT a.SId,COUNT(*) a_count
      	FROM (
      		SELECT DISTINCT SId,score
      		FROM sc
      	) a GROUP BY a.SId
      ) a
      INNER JOIN (
      	SELECT SId,COUNT(*) b_count
      	FROM sc
      	GROUP BY SId
      ) b ON a.SId=b.SId
      WHERE a.a_count!=b.b_count;
      

    9、36~40题

    • 第36题:

      • 查询每门课程成绩最好的前两名。
      • 用到的表:成绩表。
      • 前两名即比自己分高的少于两人。
      SELECT a.`SId`,c.`CId`,a.`score`
      FROM sc a
      INNER JOIN course c
      ON a.`CId`=c.CId
      INNER JOIN student d
      ON a.`SId`=d.SId
      WHERE (
      	SELECT COUNT(*)
      	FROM sc b
      	WHERE a.`CId`=b.`CId` AND a.`score`<b.`score`
      ) < 2 
      ORDER BY a.`CId`,a.`score` DESC;
      
    • 第37题:

      • 统计每门课程的学生选修人数(超过 5 人的课程才统计)。
      • 用到的表:成绩表。
      SELECT b.`Cname`,COUNT(*) c_count
      FROM sc a
      INNER JOIN course b
      ON a.`CId`=b.`CId`
      INNER JOIN student c
      ON a.`SId`=c.`SId`
      GROUP BY a.CId
      HAVING c_count>5;
      
    • 第38题:

      • 检索至少选修两门课程的学生学号 。
      • 用到的表:学生表,成绩表。
      SELECT a.`SId`,COUNT(*) c_count
      FROM sc a
      GROUP BY a.`SId`
      HAVING c_count>=2;
      
    • 第39题:

      • 查询选修了全部课程的学生信息。
      • 用到的表:学生表,成绩表,课程表。
      • 选修了所有课程就是选修课程数等于课程表中的课程数。
      SELECT c.*
      FROM sc a
      INNER JOIN student c
      ON a.`SId`=c.`SId`
      GROUP BY a.`SId`
      HAVING COUNT(*) = (
      	SELECT COUNT(*) c_count
      	FROM course
      );
      
    • 第40题:

      • 查询各学生的年龄,只按年份来算 。
      • 用到的表:学生表。
      SELECT Sname,YEAR(NOW())-YEAR(Sage) age
      FROM student;
      

    41~45题

    • 第41题:

      • 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一。
      • 用到的表:学生表。
      • 使用timestampdiff(year,小日期,大日期)
      SELECT Sname,TIMESTAMPDIFF(YEAR,Sage,NOW()) age
      FROM student;
      
    • 第42题:

      • 查询本周过生日的学生。
      • 用到的表:学生表。
      SELECT *
      FROM student
      WHERE WEEK(Sage)=WEEK(NOW());
      
      SELECT *
      FROM student
      WHERE WEEK(Sage)=WEEK("2020-12-18");
      
    • 第43题:

      • 查询下周过生日的学生。
      • 用到的表:学生表。
      • 使用DATE_ADD(Sage,INTERVAL -1 WEEK)可以获得向前一周的日期。
      SELECT *
      FROM student
      WHERE WEEK(Sage)=WEEK(NOW())+1
      OR WEEK(DATE_ADD(Sage,INTERVAL -1 WEEK))=WEEK(NOW());
      
      SELECT *
      FROM student
      WHERE WEEK(Sage)=WEEK("2020-12-29")+1
      OR WEEK(DATE_ADD(Sage,INTERVAL -1 WEEK))=WEEK("2020-12-29");
      
    • 第44题:

      • 查询本月过生日的学生。
      • 用到的表:学生表。
      SELECT *
      FROM student
      WHERE MONTH(Sage)=MONTH(NOW());
      
      SELECT *
      FROM student
      WHERE MONTH(Sage)=MONTH("2020-12-18");
      
    • 第45题:

      • 查询下月过生日的学生。
      • 用到的表:学生表。
      SELECT *
      FROM student
      WHERE MONTH(Sage)=MONTH(NOW())+1
      OR MONTH(DATE_ADD(Sage,INTERVAL -1 MONTH))=MONTH(NOW());
      
      SELECT *
      FROM student
      WHERE WEEK(Sage)=WEEK("2020-12-29")+1
      OR MONTH(DATE_ADD(Sage,INTERVAL -1 MONTH))=MONTH("2020-12-29");
      

    iwehdio的博客园:https://www.cnblogs.com/iwehdio/
    来源与结束于否定之否定。
  • 相关阅读:
    读《SQL优化核心思想》:你不知道的优化技巧
    MySQL 索引建立原则及注意事项
    MySQL 捕获有问题的SQL-慢查日志 实例
    MySQL 分区间进行数据展示 实例
    MySQL 删除重复数据实例
    MySql 索引优化实例
    JDK1.6 Java.lang.Null.Pointer.Exception
    关于 MySQL LEFT JOIN 不可不知的事
    搞定queryString
    数据库不得不说的陷阱
  • 原文地址:https://www.cnblogs.com/iwehdio/p/13916927.html
Copyright © 2011-2022 走看看