• 【MySQL】测试题03


    1、创建数据库

    CREATE DATABASE IF NOT EXISTS `exam`;
    
    • 1

    2、使用数据库

    USE exam;
    
    • 1

    3、创建数据表

    【3.1】创建学生信息表Student
    CREATE TABLE IF NOT EXISTS `Student`(
    `s_id` VARCHAR(20),
    `s_name` VARCHAR(20) NOT NULL DEFAULT '',
    `s_birth` VARCHAR(20) NOT NULL DEFAULT '',
    `s_sex` VARCHAR(10) NOT NULL DEFAULT '',
    PRIMARY KEY(`s_id`)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    【3.2】创建课程信息表Course
    CREATE TABLE IF NOT EXISTS `Course`(
    `c_id` VARCHAR(20),
    `c_name` VARCHAR(20) NOT NULL DEFAULT '',
    `t_id` VARCHAR(20) NOT NULL,
    PRIMARY KEY(`c_id`)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    【3.3】创建教师信息表Teacher
    CREATE TABLE IF NOT EXISTS `Teacher`(
    `t_id` VARCHAR(20),
    `t_name` VARCHAR(20) NOT NULL DEFAULT '',
    PRIMARY KEY(`t_id`)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    【3.4】创建成绩信息表Score
    CREATE TABLE IF NOT EXISTS `Score`(
    `s_id` VARCHAR(20),
    `c_id` VARCHAR(20),
    `s_score` INT(3),
    PRIMARY KEY(`s_id`,`c_id`)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、添加数据

    【4.1】向学生student表添加数据
    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('08' , '王菊','1990-01-20','女');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    【4.2】向课程course表添加数据
    INSERT INTO Course VALUES('01' , '语文' , '02'); 
    INSERT INTO Course VALUES('02' , '数学' , '01'); 
    INSERT INTO Course VALUES('03' , '英语' , '03');
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    【4.3】向教师信息teacher表添加数据
    INSERT INTO Teacher VALUES('01' , '张三'); 
    INSERT INTO Teacher VALUES('02' , '李四'); 
    INSERT INTO Teacher VALUES('03' , '王五');
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    【4.4】向成绩score表添加数据
    INSERT INTO Score VALUES('01' , '01' , 80);
    INSERT INTO Score VALUES('01' , '02' , 90);
    INSERT INTO Score VALUES('01' , '03' , 99);
    INSERT INTO Score VALUES('02' , '01' , 70);
    INSERT INTO Score VALUES('02' , '02' , 60);
    INSERT INTO Score VALUES('02' , '03' , 80);
    INSERT INTO Score VALUES('03' , '01' , 80);
    INSERT INTO Score VALUES('03' , '02' , 80);
    INSERT INTO Score VALUES('03' , '03' , 80);
    INSERT INTO Score VALUES('04' , '01' , 50);
    INSERT INTO Score VALUES('04' , '02' , 30);
    INSERT INTO Score VALUES('04' , '03' , 20);
    INSERT INTO Score VALUES('05' , '01' , 76);
    INSERT INTO Score VALUES('05' , '02' , 87);
    INSERT INTO Score VALUES('06' , '01' , 31);
    INSERT INTO Score VALUES('06' , '03' , 34);
    INSERT INTO Score VALUES('07' , '02' , 89);
    INSERT INTO Score VALUES('07' , '03' , 98);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    5、查询数据练习

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

      本质:行运算:比较运算
      方法:1、直接比较:子查询 2、弄成两列:自关联(注意显式连接,提升查询速度)
      备注:任一科成绩缺失不予比较

      1】直接比较:子查询

    SELECT s.*,sc.s_score
    FROM (
    SELECT sc1.s_id,sc1.s_score
    FROM score sc1
    WHERE sc1.c_id='01'
    AND sc1.s_score>(SELECT s_score FROM score WHERE s_id=sc1.s_id AND c_id='02')) sc JOIN student s ON sc.s_id=s.s_id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      2】弄成两列:自关联(注意显式连接,提升查询速度)

    SELECT s.*,sc3.s_score 
    FROM
    	(
    	SELECT sc1.s_id,sc1.s_score 
    	FROM
    		( SELECT s_id, s_score FROM score WHERE c_id = '01' ) sc1
    		JOIN ( SELECT s_id, s_score FROM score WHERE c_id = '02' ) sc2 ON sc1.s_id = sc2.s_id AND sc1.s_score > sc2.s_score 
    	) sc3
    	JOIN student s ON sc3.s_id = s.s_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      3】直接自关联

    SELECT s.*,sc1.s_score
    FROM student s 
    JOIN score sc1 ON s.s_id=sc1.s_id AND sc1.c_id='01'
    JOIN score sc2 ON s.s_id=sc2.s_id AND sc2.c_id='02' AND sc1.s_score>sc2.s_score
    
    • 1
    • 2
    • 3
    • 4

    02 查询“01”课程比“02”课程成绩低的学生的信息及课程分数(题目 1 是成绩高)

      本质:行运算:比较运算
      方法:1、直接比较:子查询 2、弄成两列:自关联(注意显式连接,提升查询速度)
      备注:任一科成绩缺失不予比较

      1】直接比较:子查询

    SELECT s.*,sc.s_score
    FROM (
    SELECT sc1.s_id,sc1.s_score
    FROM score sc1
    WHERE sc1.c_id='01'
    AND sc1.s_score<(SELECT s_score FROM score WHERE s_id=sc1.s_id AND c_id='02')) sc JOIN student s ON sc.s_id=s.s_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      2】弄成两列:自关联(注意显式连接,提升查询速度)

    SELECT s.*,sc3.s_score 
    FROM
    	(
    	SELECT sc1.s_id,sc1.s_score 
    	FROM
    		( SELECT s_id, s_score FROM score WHERE c_id = '01' ) sc1
    		JOIN ( SELECT s_id, s_score FROM score WHERE c_id = '02' ) sc2 ON sc1.s_id = sc2.s_id AND sc1.s_score < sc2.s_score 
    	) sc3
    	JOIN student s ON sc3.s_id = s.s_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      3】直接自关联

    SELECT s.*,sc1.s_score
    FROM student s 
    JOIN score sc1 ON s.s_id=sc1.s_id AND sc1.c_id='01'
    JOIN score sc2 ON s.s_id=sc2.s_id AND sc2.c_id='02' AND sc1.s_score<sc2.s_score
    
    • 1
    • 2
    • 3
    • 4

    03 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩

      本质:行聚合,后having筛选
      方法:直接聚合,后having对聚合函数进行筛选

    SELECT sc.s_id,s.s_name,ROUND(AVG(sc.s_score),0) AS score
    FROM score sc JOIN student s ON sc.s_id=s.s_id
    GROUP BY sc.s_id
    HAVING score>=60
    
    • 1
    • 2
    • 3
    • 4

      1】附加题:总分超过200分的同学

    SELECT sc.s_id,s.s_name,SUM(sc.s_score) AS score
    FROM score sc JOIN student s ON sc.s_id=s.s_id
    GROUP BY sc.s_id
    HAVING score>200
    
    • 1
    • 2
    • 3
    • 4

    04 查询平均成绩小于 60 分的同学的学生编号和学生姓名和平均成绩(包括有成绩的和无成绩的)

      本质:行聚合,后having筛选
      方法:直接聚合,聚合后用having筛选,注意主表
      备注:1、主表是学生表,没有成绩的需要包含在内,故left join 2、having可看作聚合函数的where:为空判断,比较运算,子查询 3、用ifnull处理空/left join情况

      1】null 判断

    SELECT s.s_id,s.s_name,ROUND(AVG(sc.s_score),0) AS score
    FROM student s
    LEFT JOIN score sc ON s.s_id=sc.s_id
    GROUP BY s.s_id
    HAVING score IS NULL OR score < 60

      2】ifnull 函数:更兼容

    SELECT s.s_id,s.s_name,ROUND(AVG(IFNULL(sc.s_score,0)),0) AS score
    FROM student s
    LEFT JOIN score sc ON s.s_id=sc.s_id
    GROUP BY s.s_id
    HAVING score < 60

    05 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩

      本质:行聚合
      方法:直接聚合,注意对象范围
      备注:主表是学生表,需考虑没有选课or没有成绩的情况

    SELECT s.s_id,s.s_name,
    COUNT(DISTINCT sc.c_id) AS c_num,
    SUM(sc.s_score) AS score
    FROM student s LEFT JOIN score sc ON s.s_id=sc.s_id
    GROUP BY s.s_id

      如果需要聚合后筛选,则使用if和ifnull函数
      if和ifnull是好函数,处理null情况非常方便。
      注:ifnull搭配值运算函数使用,if函数搭配count函数

    SELECT s.s_id,s.s_name,
    IF(sc.s_id IS NULL,0,COUNT(DISTINCT sc.c_id)) AS c_num,
    SUM(IFNULL(sc.s_score,0)) AS score
    FROM student s LEFT JOIN score sc ON s.s_id=sc.s_id
    GROUP BY s.s_id

    06 查询“李”姓老师的数量

      本质:行筛选聚合
      方法:筛选计数
      问题:like是最优的吗

      1】like通配符

    SELECT COUNT(DISTINCT t_id) AS t_num
    FROM Teacher
    WHERE t_name LIKE ‘李%’

      2】截取姓氏,然后判断

    SELECT COUNT(DISTINCT t_id) AS t_num
    FROM Teacher
    WHERE SUBSTR(t_name,1,1)=‘李’

    07 查询学过张三老师授课的同学的信息

      本质:行筛选:逐级
      方法:表关联or子查询
      1】逐级子查询,这样更好理解

    SELECT s.*
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    WHERE c_id IN(SELECT c_id FROM Course WHERE t_id IN(SELECT t_id FROM Teacher WHERE t_name=‘张三’))

      2】表关联

    SELECT s.*
    FROM score sc
    JOIN course c ON c.c_id=sc.c_id
    JOIN teacher t ON t.t_id=c.t_id AND t.t_name=‘张三’
    JOIN student s ON sc.s_id=s.s_id

    08 找出没有学过张三老师课程的学生

      本质:反向行筛选
      方法:按照学过筛选,最后取相反情况left join 或right join,且is null

      1】表关联

    SELECT s.*
    FROM score sc
    JOIN course c ON c.c_id=sc.c_id
    JOIN teacher t ON t.t_id=c.t_id AND t.t_name=‘张三’
    RIGHT JOIN student s ON sc.s_id=s.s_id
    WHERE sc.s_id IS NULL

      1】not in,这个好理解

    SELECT *
    FROM student
    WHERE s_id NOT IN(
    SELECT sc.s_id
    FROM score sc
    JOIN course c ON c.c_id=sc.c_id
    JOIN teacher t ON t.t_id=c.t_id AND t.t_name=‘张三’
    )

    09 查询学过编号为 01,并且学过编号为 02 课程的学生信息

      本质:行筛选:取交集
      方法:自关联 or 子查询

      1】自关联

    SELECT s.*
    FROM Score sc1
    JOIN Score sc2 ON sc1.s_id=sc2.s_id AND sc1.c_id=‘01’ AND sc2.c_id=‘02’
    JOIN Student s ON sc1.s_id=s.s_id

      1】子查询

    SELECT s.*
    FROM Score sc1
    JOIN Student s ON sc1.s_id=s.s_id
    WHERE sc1.c_id=‘01’
    AND sc1.s_id IN(SELECT s_id FROM Score sc2 WHERE sc1.s_id=sc2.s_id AND sc2.c_id=‘02’)

    10 查询学过 01 课程,但是没有学过 02 课程的学生信息(注意和上面9题目的区别)

      本质 行筛选:取交集
      方法 子查询,不能使用自关联,因为一条cid一条记录,不能用否判断

    SELECT s.*
    FROM Score sc1
    JOIN Student s ON sc1.s_id=s.s_id
    WHERE sc1.c_id=‘01’
    AND sc1.s_id NOT IN(SELECT s_id FROM Score sc2 WHERE sc1.s_id=sc2.s_id AND sc2.c_id=‘02’)

    11 查询没有学完全部课程的同学的信息

      本质:行聚合,后having筛选
      方法 直接聚合,注意表对象范围
      备注 having可看作聚合函数的where:为空判断,比较运算,子查询

    SELECT s.*
    FROM student s
    LEFT JOIN score sc ON sc.s_id=s.s_id
    GROUP BY s.s_id
    HAVING COUNT(DISTINCT sc.c_id)<(SELECT COUNT(*) FROM course)

      发现筛选,先筛选出学完全部课程的同学

    SELECT *
    FROM Student
    WHERE s_id NOT IN(SELECT s_id FROM Score GROUP BY s_id HAVING COUNT(c_id)=(SELECT COUNT(*) FROM Course))

    12 查询至少有一门课与学号为 01 的同学所学相同的同学的信息

      本质 行筛选:子查询
      方法 1、学号01所学课程c_id01 2、学号不等于01且c_id in c_id01

    SELECT s.*
    FROM score sc
    JOIN student s ON sc.s_id=s.s_id AND sc.s_id<>‘01’
    WHERE sc.c_id IN(SELECT c_id FROM score WHERE s_id=‘01’)
    GROUP BY s.s_id

    13 查询和 01 同学学习的课程完全相同的同学的信息

    #本质 行筛选:子查询
    #方法 1、学号01所学课程 2、和01所学相同课程且课程数等于01课程数
    #备注 关键是思考方法
    #group_concat()函数用法
    #group_concat([DISTINCT] 字 段 [Order BY ASC/DESC 排序字段] [Separator ‘分隔符’])

      1】方法1 课程相同的数量相同

    SELECT s.*
    FROM score sc
    JOIN student s ON sc.s_id=s.s_id

      课程数量相等

    WHERE sc.s_id IN(SELECT s_id FROM Score WHERE s_id <>‘01’ GROUP BY s_id HAVING COUNT(DISTINCT c_id)=(SELECT COUNT(DISTINCT c_id) FROM score WHERE s_id=‘01’))

      课程相同的数量相同

    AND c_id IN(SELECT c_id FROM score WHERE s_id=‘01’)
    GROUP BY s.s_id
    HAVING COUNT(DISTINCT sc.c_id)=(SELECT COUNT(DISTINCT c_id) FROM score WHERE s_id=‘01’)

      2】使用group_concat()函数,如果记录数比较大,建议采用方法1

    SELECT s.*
    FROM student s
    JOIN score sc ON s.s_id=sc.s_id AND sc.s_id<>‘01’
    GROUP BY s.s_id
    HAVING GROUP_CONCAT(sc.c_id ORDER BY sc.c_id)=
    (SELECT GROUP_CONCAT(c_id ORDER BY c_id) FROM score WHERE s_id=‘01’ GROUP BY s_id)

    14 查询没有修过张三老师讲授的任何一门课程的学生姓名

    #本质 反向行筛选
    #方法 修过张三老师任一门课即不符合要求
    #备注 注意表对象是全体学生,主表是学生表,因对s_id筛选,故不用再和score关联

    SELECT s_name
    FROM student
    WHERE s_id NOT IN(
    SELECT s_id FROM score
    WHERE c_id IN(SELECT c_id FROM course WHERE t_id=(SELECT t_id FROM teacher WHERE t_name=‘张三’)))

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

    #本质 行筛选并聚合
    #方法 1、行筛选:及格与否 2、求不及格课程数 3、having筛选
    #备注 修过才会有及格与否之说,故score为主表

      1】方式1

    SELECT sc.s_id,s.s_name,ROUND(AVG(sc.s_score),0) AS avg_score
    FROM score sc
    JOIN student s ON sc.s_id=s.s_id
    GROUP BY sc.s_id
    HAVING SUM(IF(sc.s_score<60,1,0))>=2

      2】方式2 查询表更小

    SELECT sc.s_id,s.s_name,ROUND(AVG(sc.s_score),0) AS avg_score
    FROM score sc
    JOIN student s ON sc.s_id=s.s_id AND sc.s_score<60
    GROUP BY sc.s_id
    HAVING COUNT(*)>=2

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

    #本质 行筛选并排序
    #方法 分数<60、分数降序
    #备注 排序函数区别 1、row_number()over:123 2、rank()over():113 3、dense_rank()over():112

    SELECT s.*
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    WHERE c_id=‘01’
    AND s_score<60
    ORDER BY s_score DESC

    17 按平均成绩从高到低(降序)显示所有学生的所有课程的成绩以及平均成绩

    #本质 表关联并排序
    #方法 找到主表,找到排序字段
    #备注 如何将排序字段和其他字段关联是关键点,这里的平均成绩是所选课程的平均成绩

      1】纵表

    SELECT s.s_name,c.c_name,sc.s_score,sc2.avg_score
    FROM Student s
    JOIN Course c
    LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
    LEFT JOIN (SELECT s_id,ROUND(AVG(s_score),0) AS avg_score FROM Score GROUP BY s_id) sc2 ON s.s_id=sc2.s_id
    ORDER BY sc2.avg_score DESC

      2】横表

    SELECT s.s_name,
    MAX(CASE sc.c_id WHEN ‘01’ THEN sc.s_score END) AS ‘语文’,
    MAX(CASE sc.c_id WHEN ‘02’ THEN sc.s_score END) AS ‘数学’,
    MAX(CASE sc.c_id WHEN ‘03’ THEN sc.s_score END) AS ‘英语’,
    sc2.avg_score AS ‘平均成绩’
    FROM Student s
    JOIN Course c
    LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
    LEFT JOIN (SELECT s_id,ROUND(AVG(s_score),0) AS avg_score FROM Score GROUP BY s_id) sc2 ON s.s_id=sc2.s_id
    GROUP BY s.s_name,sc2.avg_score
    ORDER BY sc2.avg_score DESC

    18 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格 率,中等率,优良率,优秀率;及格:>=60,中等为:70-80,优良为:80-90,优秀为:>=90

    #本质 表关联并聚合
    #方法 主表course,left join 成绩表score,求最值、均值及分组
    #备注 注意小数位数及百分率符号

    SELECT c.c_id AS ‘课程id’,c.c_name AS ‘课程name’,
    MAX(sc.s_score) AS ‘最高分’,
    MIN(sc.s_score) AS ‘最低分’,
    ROUND(AVG(sc.s_score),2) AS ‘平均分’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=60,1,0))/COUNT(sc.s_id)*100,2),‘%’) AS ‘及格率’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=70 AND sc.s_score<80,1,0))/COUNT(sc.s_id)*100,2),‘%’) AS ‘中等率’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=80 AND sc.s_score<90,1,0))/COUNT(sc.s_id)*100,2),‘%’) AS ‘优良率’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=90,1,0))/COUNT(sc.s_id)*100,2),‘%’) AS ‘优秀率’
    FROM Course c
    LEFT JOIN Score sc ON c.c_id=sc.c_id
    GROUP BY c.c_id

    19 按照各科成绩进行排序,并且显示排名

    #本质 分组排序
    #方法 选择排序依据并排名

    SELECT c.c_name,s.s_name,sc.s_score,
    ROW_NUMBER() OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS ‘排名’
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    JOIN Course c ON sc.c_id=c.c_id

    20 查询学生的总成绩,并进行排名

    #本质 行聚合后排序
    #方法 sum、排序

    SELECT s.s_name,SUM(sc.s_score) AS ‘总成绩’,
    ROW_NUMBER()OVER(ORDER BY SUM(sc.s_score) DESC) AS ‘排名’
    FROM Student s
    LEFT JOIN Score sc ON s.s_id=sc.s_id
    GROUP BY s.s_name

    21 查询不同老师所教不同课程平均分从高到低显示

    #本质 表关联后聚合再排序
    #方法 主表是教师表teacher和课程表course笛卡尔积,left join 成绩表score,求均值后order by

    SELECT t.t_name,c.c_name,ROUND(AVG(sc.s_score),2) AS ‘平均分’
    FROM Teacher t
    JOIN Course c ON t.t_id=c.t_id
    LEFT JOIN Score sc ON c.c_id=sc.c_id
    GROUP BY t.t_name,c.c_name
    ORDER BY AVG(sc.s_score) DESC

    22 查询所有课程的成绩第 2 名到第 3 名的学生信息及该课程成绩

    #本质 行排序后筛选
    #方法 所有课程成绩排名,再取2和3名

    SELECT r.c_name,r.rank_num,s.s_name,r.s_score
    FROM
    (SELECT c.c_name,sc.s_id,sc.s_score,
    ROW_NUMBER()OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS rank_num
    FROM Course c
    LEFT JOIN Score sc ON c.c_id=sc.c_id)r
    JOIN Student s ON r.s_id=s.s_id AND r.rank_num IN(2,3)

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

    #本质 行分组聚合
    #方法 先列基本:科目、成绩,后分组计数

    SELECT sc.c_id,c.c_name,
    SUM(IF(sc.s_score>=85,1,0)) AS ‘[100-85]人数’,
    SUM(IF(sc.s_score>=70 AND sc.s_score<85,1,0)) AS ‘[85-70]人数’,
    SUM(IF(sc.s_score>=60 AND sc.s_score<70,1,0)) AS ‘[70-60]人数’,
    SUM(IF(sc.s_score<60,1,0)) AS ‘[0-60]人数’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=85,1,0))/COUNT(*)100,2),‘%’) AS ‘[100-85]百分比’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=70 AND sc.s_score<85,1,0))/COUNT(
    )100,2),‘%’) AS ‘[85-70]百分比’,
    CONCAT(ROUND(SUM(IF(sc.s_score>=60 AND sc.s_score<70,1,0))/COUNT(
    )100,2),‘%’) AS ‘[70-60]百分比’,
    CONCAT(ROUND(SUM(IF(sc.s_score<60,1,0))/COUNT(
    )*100,2),‘%’) AS ‘[0-60]百分比’
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id
    GROUP BY sc.c_id

    24 查询学生的平均成绩及名次

    #本质 行聚合后排序
    #方法 求平均成绩,后排序

    SELECT s.s_name,ROUND(AVG(sc.s_score),2) AS ‘总成绩’,
    ROW_NUMBER()OVER(ORDER BY AVG(sc.s_score) DESC) AS ‘排名’
    FROM Student s
    LEFT JOIN Score sc ON s.s_id=sc.s_id
    GROUP BY s.s_name

    25 查询各科成绩前三名的记录

    #本质 行排序后筛选
    #方法 各科成绩排序,取前3

    SELECT r.c_name,r.rank_num,s.s_name,r.s_score
    FROM
    (SELECT c.c_name,sc.s_id,sc.s_score,
    ROW_NUMBER()OVER(PARTITION BY c.c_name ORDER BY sc.s_score DESC) AS rank_num
    FROM Course c
    LEFT JOIN Score sc ON c.c_id=sc.c_id)r
    JOIN Student s ON r.s_id=s.s_id AND r.rank_num<=3

    26 查询每门课被选修的学生数

    #本质 行聚合
    #方法 成绩表按科目对s_id计数

    SELECT c.c_name,COUNT(DISTINCT sc.s_id) AS s_num
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id
    GROUP BY c.c_name

    27 查询出只有两门课程的全部学生的学号和姓名

    #本质 行聚合
    #方法 成绩表按学生对c_id计数

    SELECT s.s_id,s.s_name
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    GROUP BY s.s_id
    HAVING COUNT(DISTINCT sc.c_id)=2

    28 查询男女生人数

    #本质 行筛选聚合
    #方法 学生表student按性别分组计数

    SELECT s_sex,COUNT(DISTINCT s_id) AS ‘人数’
    FROM Student
    GROUP BY s_sex

    29 查询名字中含有 风 字的学生信息

    #本质 模糊筛选
    #方法

    SELECT *
    FROM Student
    WHERE s_name LIKE ‘%风%’

    30 查询同名同性的学生名单,并统计同名人数

    #本质 分组聚合
    #方法 分组计数后having筛选

    SELECT s1.s_name,s1.s_sex,s2.num AS ‘同名人数’
    FROM Student s1
    JOIN (SELECT s_name,COUNT() AS num FROM Student GROUP BY s_name HAVING COUNT()>=2)s2 ON s1.s_name=s2.s_name
    GROUP BY s1.s_name,s1.s_sex
    HAVING COUNT(*)>=2

    31 查询 1990 年出生的学生信息

    #本质 行筛选
    #方法 获取出生年份,并筛选
    #备注 DATE()可以将varchar转成日期型 YEAR()函数返回一个指定日期or时间的年份值,范围为1000到9999,如果日期为零,YEAR()函数返回0

    SELECT *
    FROM Student
    WHERE YEAR(DATE(s_birth))=1990

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

    #本质 行聚合后排序
    #方法 对课程求均值,后排序
    #备注 order by后可跟聚合函数

    SELECT c.c_name,ROUND(AVG(sc.s_score),2) AS ‘平均分’
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id
    GROUP BY c.c_id
    ORDER BY AVG(sc.s_score) DESC,c.c_id ASC

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

    #本质 行聚合后筛选
    #方法 对学生求成绩均值,后筛选

    SELECT s.s_id,s.s_name,ROUND(AVG(sc.s_score),2) AS ‘平均成绩’
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    GROUP BY s.s_id
    HAVING AVG(sc.s_score)>=85

    34 查询课程名称为数学,且分数低于 60 的学生姓名和分数

    #本质 行筛选
    #方法 按要求筛选,用到子查询

    SELECT s.s_name,sc.s_score
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    WHERE c_id=(SELECT c_id FROM Course WHERE c_name=‘数学’)
    AND s_score<60

    35 查询所有学生的课程及分数情况

    #本质 表关联后聚合
    #方法 学生表与课程表笛卡尔积,获取所有学生及所有课程,然后关联成绩表获取成绩,最后聚合 注:成绩表为窄表,故外层需要聚合

    SELECT s.s_name,
    SUM(CASE c.c_name WHEN ‘语文’ THEN sc.s_score ELSE 0 END) AS ‘语文’,
    SUM(CASE c.c_name WHEN ‘数学’ THEN sc.s_score ELSE 0 END) AS ‘数学’,
    SUM(CASE c.c_name WHEN ‘英语’ THEN sc.s_score ELSE 0 END) AS ‘英语’,
    SUM(sc.s_score) AS ‘总分’
    FROM Student s
    JOIN Course c
    LEFT JOIN Score sc ON s.s_id=sc.s_id AND c.c_id=sc.c_id
    GROUP BY s.s_name

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

    #本质 行筛选
    #方法 成绩表筛选>70

    SELECT s.s_name,c.c_name,sc.s_score
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    JOIN Course c ON sc.s_id=c.c_id
    WHERE s_score>70

    37 查询不及格的课程

    #本质 行筛选

    SELECT sc.c_id,c.c_name,sc.s_score
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id
    WHERE sc.s_score<60

    38 查询课程编号为 01 且课程成绩大于等于 80 的学生的学号和姓名

    #本质 行筛选

    SELECT s.s_id,s.s_name
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    WHERE c_id=‘01’
    AND s_score>=80

    39 每门课程的学生人数

    #本质 行聚合

    SELECT c.c_name,COUNT(DISTINCT sc.s_id) AS ‘人数’
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id
    GROUP BY c.c_name

    40 查询选修“张三”老师所授课程的学生中,成绩最高的学生信息及其成绩

    #本质 行筛选后聚合
    #方法 张三老师所授课程中,成绩最高(max、order by、row_number()over)的学生 1、max需要关联表匹配 2、order by和limit 1配合使用,推荐 3、row_number()over需要外层表限制rank_num=1

    SELECT s.*,s_score
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    WHERE c_id=(SELECT c_id FROM Course WHERE t_id=(SELECT t_id FROM Teacher WHERE t_name=‘张三’))
    ORDER BY s_score DESC
    LIMIT 1

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

    #本质 行筛选
    #方法 符合条件的成绩:按成绩分组,对课程id计数且>2

    SELECT *
    FROM Score
    WHERE s_score IN(SELECT s_score FROM Score GROUP BY s_score HAVING COUNT(DISTINCT c_id)>=2)

    42 查询每门功成绩最好的前两名

    #本质 行排序后筛选
    #方法 这里分组取前两名,需窗口函数row_number()over

    SELECT r.*
    FROM(
    SELECT c_name,s_id,s_score,
    ROW_NUMBER()OVER(PARTITION BY c_name ORDER BY s_score DESC) AS rank_num
    FROM Score sc
    JOIN Course c ON sc.c_id=c.c_id)r
    WHERE r.rank_num<=2

    43 统计每门课程的学生选修人数(超过 5 人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列, 若人数相同,按课程号升序排列

    #本质 行聚合后排序

    SELECT c_id,COUNT(DISTINCT s_id) AS ‘人数’
    FROM Score
    GROUP BY c_id
    ORDER BY ‘人数’ DESC,c_id ASC

    44 检索至少选修两门课程的学生学号

    #本质 行聚合后筛选

    SELECT s_id
    FROM Score
    GROUP BY s_id
    HAVING COUNT(DISTINCT c_id)>=2

    45 查询选修了全部课程的学生信息

    #本质 行聚合后筛选

    SELECT s.*
    FROM Score sc
    JOIN Student s ON sc.s_id=s.s_id
    GROUP BY s.s_id
    HAVING COUNT(DISTINCT c_id)=(SELECT COUNT(*) FROM Course)

    46 查询各学生的年龄:按照出生日期来算,当前月日 < 出生年月的月日则,年龄减 1

    #本质 行筛选:日期-年月日
    #方法 年月日获取year()、month()、day()

    SELECT *,
    CASE
    WHEN MONTH(NOW()) YEAR(NOW())-YEAR(DATE(s_birth))-1
    WHEN MONTH(NOW())=MONTH(DATE(s_birth)) AND DAY(NOW()) YEAR(NOW())-YEAR(DATE(s_birth))-1
    ELSE
    YEAR(NOW())-YEAR(DATE(s_birth))
    END AS age
    FROM Student

    47 查询本周过生日的学生

    #本质 行筛选:日期-周
    #方法 周获取week()

    SELECT *
    FROM Student
    WHERE WEEK(DATE(s_birth))=WEEK(NOW())

    48 查询下周过生日的学生

    #本质 行筛选:日期-周
    #方法 周获取week()

    SELECT *
    FROM Student
    WHERE WEEK(DATE(s_birth))=WEEK(NOW())+1

    49 查询本月过生的同学

    #本质 行筛选:日期-月

    SELECT *
    FROM Student
    WHERE MONTH(DATE(s_birth))=MONTH(NOW())

    50 查询下月过生的同学

    #本质 行筛选:日期-月

    SELECT *
    FROM Student
    WHERE MONTH(DATE(s_birth))=MONTH(NOW())+1

  • 相关阅读:
    北斗导航 | RTCM 3.3学习(10403.3)
    JavaScript中的浅拷贝和深拷贝
    【无标题】
    【Seata源码学习 】 篇二 TM与RM初始化过程
    PT_离散型随机变量下的分布:几何/超几何/幂律
    windows 系统下 设置 redis开机自启动
    使用Scrcpy投屏
    平面扫描(Plane-sweeping)深度体会
    阿里云主要产品有哪些?有什么用?
    2022年起重信号司索工(建筑特殊工种)上岗证题目及在线模拟考试
  • 原文地址:https://blog.csdn.net/hh867308122/article/details/127960459