• MySQL学习笔记——〇三 MySQL习题


    在前面讲了MySQL的初步使用方法以后,在这里放出来一些案例来看看怎么做。

    先看看database的结构,一共5个表

     外键关系:

    class的cid是student的class_id的外键,teacher表的tid是course的teacher_id的外键,student表的sid和course表的cid是score表的student_id和course_id的外键,student_id和course_id是联合唯一索引。

    写的可能不太清楚,大概就是这么个关系,数据没有完全列出来。

    表的创建和数据插入代码

    表和数据的代码

    下面就是SQL语句的使用

    1.查询“生物”课程比“物理”课程成绩高的所有学生的学号

    思路:分别获取生物的成绩和物理的成绩,连表以后取student_id相同的数据就是学习了物理和生物的同学,再用where筛选

    SELECT
        t1.sid 
    FROM
        ( SELECT * FROM score LEFT JOIN course ON course.cid = score.course_id WHERE course.cname = '生物' ) AS t1
        LEFT JOIN ( SELECT * FROM score LEFT JOIN course ON course.cid = score.course_id WHERE course.cname = '物理' ) AS t2 ON t1.student_id = t2.student_id 
    WHERE
        t1.num > t2.num;
    View Code

    2.查询平均成绩大于60分的同学的学号和平均成绩

    SELECT
        student_id,
        AVG( num ) 
    FROM
        score 
    GROUP BY
        student_id 
    HAVING
        AVG( num )> 60;
    View Code

    3.查询所有同学的学号、姓名、选课数、总成绩

    SELECT
        student.sid,
        student.sname,
        t.totle_course,
        t.totle_score 
    FROM
        ( SELECT student_id, count( course_id ) AS totle_course, sum( num ) AS totle_score FROM score GROUP BY student_id ) AS t
        JOIN student ON t.student_id = student.sid;
    方法1
    SELECT
        score.student_id,
        student.sname,
        count( student_id ),
        sum( num ) 
    FROM
        score
        LEFT JOIN student ON student_id = student.sid 
    GROUP BY
        score.student_id;
    方法2

     4.查询姓“李”的老师的个数

    SELECT
        count( 1 ) 
    FROM
        teacher 
    WHERE
        tname LIKE '李%';
    View Code

    5.查询没学过“李平”老师课的同学的学号、姓名

    先获取李平老师的tid,在根据tid获取course里的cid,根据cid获取score表内not in cid的student_id,然后连表查sname就可以了

    SELECT
        sid,
        sname 
    FROM
        student 
    WHERE
        sid NOT IN (
        SELECT
            student_id 
        FROM
            score 
        WHERE
            course_id IN ( SELECT cid FROM course LEFT JOIN teacher ON course.teacher_id = teacher.tid WHERE teacher.tname = '李平老师' ) 
    GROUP BY
        student_id);
    View Code

    6.查询学过“李平”老师所教的所有课的同学的学号、姓名

    和上一道题差不多,但是是学过全部课程的

    SELECT
        t.student_id,
        student.sname 
    FROM
        (
        SELECT
            student_id 
        FROM
            score 
        WHERE
            course_id IN ( SELECT cid FROM course LEFT JOIN teacher ON teacher.tid = course.teacher_id WHERE tname = '李平老师' ) 
        GROUP BY
            student_id 
        HAVING
            count( course_id )> 1 
        ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

    7.查询学过“001”并且也学过编号“002”课程的同学的学号、姓名

    SELECT
        t.student_id,
        student.sname 
    FROM
        ( SELECT student_id FROM score WHERE course_id = 1 OR course_id = 2 GROUP BY student_id HAVING count( course_id )> 1 ) AS t
        LEFT JOIN student ON t.student_id = student.sid;
    View Code

    8.查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名

    和第1题思路一样,题里直接给出了课程的id,少了一步索引。反而更简单

    SELECT
        t.student_id,
        student.sname 
    FROM
        (
        SELECT
            t1.student_id 
        FROM
            ( SELECT * FROM score WHERE course_id = 1 ) AS t1
            LEFT JOIN ( SELECT * FROM score WHERE course_id = 2 ) AS t2 ON t1.student_id = t2.student_id 
        WHERE
            t2.num < t1.num 
        ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

    9.查询有课程成绩小于60分的同学的学号、姓名

    获取了score里num少于60的数据以后student_id里可能会有重复的,如果用distinct的话也是可以的,但是distinct在数据量较大的时候去重效率就会比较低下。所以在这里用了group by。

    SELECT
        Id,
    NAME 
    FROM
        (
        SELECT
            student.sid AS Id,
            student.sname AS NAME 
        FROM
            score
            LEFT JOIN student ON student.sid = score.student_id 
        WHERE
            num < 60 
        ) AS t 
    GROUP BY
        Id;
    View Code

    10.查询没有学全所有课的同学的学号、姓名

    这里用动态获取课程数量的方法,没有把课程数量写死。

    SELECT
        t.student_id,
        student.sname 
    FROM
        (
        SELECT
            student_id 
        FROM
            score 
        GROUP BY
            student_id 
        HAVING
            count( course_id )<(
            SELECT
                count( 1 ) 
            FROM
                course 
            )) AS t
        LEFT JOIN student ON student.sid = t.student_id
    View Code

    11.查询至少有一门课与学号为“001”的同学所学相同的同学的学号和姓名

    SELECT
        t.student_id,
        student.sname 
    FROM
        ( SELECT student_id FROM score WHERE student_id != 1 AND course_id IN ( SELECT course_id FROM score WHERE student_id = 1 ) GROUP BY student_id ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

    12.查询至少学过学号为“001”同学所有课的其他同学学号和姓名

    SELECT
        t.id,
        student.sname 
    FROM
        (
        SELECT
            student_id AS id,
            count( 1 ) 
        FROM
            score 
        WHERE
            student_id != 1 
            AND course_id IN ( SELECT course_id FROM score WHERE student_id = 1 ) 
        GROUP BY
            student_id 
        HAVING
            count( 1 ) = ( SELECT count( course_id ) FROM score WHERE student_id = 1 ) 
        ) AS t
        LEFT JOIN student ON student.sid = t.id;
    View Code

    13.查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名

    14.删除学习“李平”老师课的SC表记录

    DELETE 
    FROM
        score 
    WHERE
        course_id IN (
        SELECT
            cid 
        FROM
            course 
    WHERE
        teacher_id IN ( SELECT tid FROM teacher WHERE tname = '李平老师' ));
    View Code

    15.向SC表中插入一些记录,这些记录要求符合以下条件:①没有上过编号“002”课程的同学学号;②插入“002”号课程的平均成绩

    insert into score(student_id, course_id, num) select sid,2,(select avg(num) from score where course_id = 2)
        from student where sid not in (
            select student_id from score where course_id = 2
        );
    View Code

    16.按平均成绩从低到高显示所有学生的“001”、“002”、“003”三门的课程成绩,按如下形式显示: 学生ID,语文,数学,英语,有效课程数,有效平均分(重要方法);

    这个题的解法还是很重要的,一定要掌握,先看看怎么获取各学员的三门成绩

    SELECT
        student_id,
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 1 ) AS 'course1_num',
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 2 ) AS 'course2_num',
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 3 ) AS 'course3_num' 
    FROM
        score AS s1 
    GROUP BY
        student_id

    最后再分下组就可以了

    SELECT
        student_id,
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 1 ) AS 'course1_num',
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 2 ) AS 'course2_num',
        ( SELECT num FROM score AS s2 WHERE s2.student_id = s1.student_id AND course_id = 3 ) AS 'course3_num',
        count( s1.course_id ) AS 有效课程数,
        avg( s1.num ) AS 平均分 
    FROM
        score AS s1 
    GROUP BY
        student_id 
    ORDER BY
        平均分 DESC;
    16题解法

    17.查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

    select course_id,max(num)as 最高分,min(num) as 最低分 from score group by course_id;
    View Code

    18.按各科平均成绩从低到高和及格率的百分数从高到低顺序(case when else的用法) 

    思路,在select的时候添加两列数,一列根据num判定是否及格,及格了赋值为1要么就赋值为0另外一列直接count(1),最后两列用sum统计一下再一除就知道及格率是多少了

    SELECT
        course_id,
        avg( num ) AS 平均分,
        sum( CASE WHEN num < 60 THEN 0 ELSE 1 END )/ sum( 1 ) AS 及格率 
    FROM
        score 
    GROUP BY
        course_id 
    ORDER BY
        平均分 ASC,及格率 DESC;
    View Code

    19.课程平均分从高到低显示(显示任课老师)

    三元运算的方式限制了一下,防止某人的成绩为空然后运算报错

    if(isnull(score.num),0,score.num)
    SELECT
        score.course_id,
        avg(if(isnull(score.num),0,score.num)),
        teacher.tname 
    FROM
        score
        LEFT JOIN course ON score.course_id = course.cid
        LEFT JOIN teacher ON course.teacher_id = teacher.tid 
    GROUP BY
        course_id 
    ORDER BY
        avg( num ) DESC;
    View Code

    20.查询各科成绩前三名的记录:(不考虑成绩并列情况)

    这里的思路可能比较绕,方法是先按course_id进行分组,获取每门学科的成绩,在group by 去重后进行降序排列后用limit2,1来获取每一科拍第三的成绩,

    SELECT
        course_id,
        ( SELECT num FROM score AS s2 WHERE s2.course_id = s1.course_id GROUP BY s2.num DESC LIMIT 2, 1 ) AS num3 
    FROM
        score AS s1

    然后连表到score以后再比较course_id和num,在course_id相同的时候看看如果num大于num3,就满足要求

    SELECT
        * 
    FROM
        (
        SELECT
            student_id,
            course_id,
            num,
            ( SELECT num FROM score AS s2 WHERE s2.course_id = s1.course_id GROUP BY s2.num DESC LIMIT 2, 1 ) AS num3 
        FROM
            score AS s1 
        ) AS t 
    WHERE
        num > num3 
    ORDER BY
        course_id ASC,
        num3 DESC;
    View Code

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

    SELECT
        course_id,
        count( 1 ) 
    FROM
        score 
    GROUP BY
        course_id;
    View Code

    22.查询出只选修了一门课程的全部学生的学号和姓名

    SELECT
        student.sid,
        student.sname 
    FROM
        ( SELECT student_id FROM score GROUP BY student_id HAVING count( 1 ) = 1 ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

    23.查询男生、女生的人数

    SELECT
        gender,
        count( 1 ) 
    FROM
        student 
    GROUP BY
        gender;
    View Code

    24.查询姓“张”的学生名单

    SELECT
        * 
    FROM
        student 
    WHERE
        sname LIKE '张%';
    View Code

    25.查询同名同姓学生名单,并统计同名人数

    SELECT
        sname,
        count( 1 ) 
    FROM
        student 
    GROUP BY
        sname;
    View Code

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

    SELECT
        course_id,
        avg( num ) 
    FROM
        score 
    GROUP BY
        course_id 
    ORDER BY
        avg( num ) ASC,
        course_id DESC;
    View Code

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

    SELECT
        student.sid,
        student.sname,
        t.average 
    FROM
        ( SELECT student_id, avg( num ) AS average FROM score GROUP BY student_id HAVING average > 85 ) AS t
        JOIN student ON student.sid = t.student_id;
    View Code

    28.查询课程名称为“生物”,且分数低于60的学生姓名和分数

    SELECT
        student.sname,
        t.num 
    FROM
        ( SELECT student_id, num FROM score WHERE course_id = ( SELECT cid FROM course WHERE cname = '生物' ) AND num < 60 ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

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

    SELECT
        student.sid,
        student.sname 
    FROM
        ( SELECT student_id FROM score WHERE course_id = 3 AND num >= 80 ) AS t
        LEFT JOIN student ON student.sid = t.student_id;
    View Code

    30.求选了课程的学生人数

    select student_id from score group by student_id;
    View Code

    31.查询选修“张磊”老师所授课程的学生中,成绩最高的学生姓名及其成绩

    SELECT
        student.sname,
        num 
    FROM
        score
        LEFT JOIN student ON score.student_id = student.sid 
    WHERE
        course_id = ( SELECT cid FROM course WHERE teacher_id = ( SELECT tid FROM teacher WHERE tname = '张磊老师' ) ) 
    ORDER BY
        num DESC 
        LIMIT 1;
    View Code

    32.查询各个课程及相应的选修人数

    select course_id,count(1) from score group by course_id;
    View Code

    33.查询不同课程但成绩相同的学生的学号、课程号、学生成绩

    这里有个比较有意思的用法,假设我们有一个这样的表(表的名称就叫t吧)

    然后我们执行下面的语句

    select* from t as s1 ,t as s2;

    出来的回事什么样的结论呢?

    我们就可以利用这个方式来筛选一行中不同两列数据一样的值是否一样了

    SELECT
        s1.student_id,
        s1.course_id,
        s2.course_id,
        s2.num 
    FROM
        score AS s1,
        score s2 
    WHERE
        s1.sid != s2.sid 
        AND s1.course_id != s2.course_id 
        AND s1.num = s2.num 
        AND s1.student_id = s2.student_id;
    View Code

    34.查询每门课程成绩最好的前两名

    和前面第20题思路一样

    SELECT
        * 
    FROM
        (
        SELECT
            student_id,
            course_id,
            num,
            ( SELECT num FROM score AS s2 WHERE s2.course_id = s1.course_id GROUP BY s2.num DESC LIMIT 1, 1 ) AS num3 
        FROM
            score AS s1 
        ) AS t 
    WHERE
        num > num3 
    ORDER BY
        course_id ASC,
        num3 DESC;
    View Code

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

    SELECT
        student_id 
    FROM
        score 
    GROUP BY
        student_id 
    HAVING
        count( 1 ) > 1;
    View Code

    36.查询全部学生都选修的课程的课程号和课程名

    SELECT
        course.cid,
        course.cname 
    FROM
        (
        SELECT
            course_id 
        FROM
            score 
        GROUP BY
            course_id 
        HAVING
            count( 1 )=(
            SELECT
                count( 1 ) 
            FROM
                student 
            )) AS t
        LEFT JOIN course ON course.cid = t.course_id;
    View Code

    37.查询没学过“李平”老师讲授的任一门课程的学生姓名

    SELECT
        sid,
        sname 
    FROM
        student 
    WHERE
        sid NOT IN ((
            SELECT
                student_id 
            FROM
                score 
            WHERE
                course_id IN (
                SELECT
                    cid 
                FROM
                    course 
                WHERE
                teacher_id IN ( SELECT tid FROM teacher WHERE tname = '李平老师' )) 
            GROUP BY
            student_id 
        ));
    View Code

    38.查询两门以上不及格课程的同学的学号及其平均成绩

    SELECT
        student_id,
        avg( num ) 
    FROM
        score 
    WHERE
        num < 60 
    GROUP BY
        student_id 
    HAVING
        count( 1 )> 2;
    View Code

    39.检索“004”课程分数小于60,按分数降序排列的同学学号

    SELECT
        student_id 
    FROM
        score 
    WHERE
        num < 60 
        AND course_id = 4 
    ORDER BY
        student_id DESC;
    View Code

    40.删除“002”同学的“001”课程的成绩

    DELETE from score where student_id=2 and course_id=1;
    View Code
     

    基本上常用的数据操作的方法都在上面列出来了,但是在日常的使用中我们一般不会有这么多需要连表的地方,一般我们会牺牲 一些存储空间来减少数据库来回连表的情况,可以提高一定的效率。

  • 相关阅读:
    LIBTIFF 配置 (vs2010 + win8 + 32位 )
    minGW、cygwin、gnuwin32 介绍
    LabVIEW发布功能总结
    LabVIEW新手5大错误
    专业功放测试:主要性能指标&信噪比测量
    常用低压电器的主要种类和用途
    LabVIEW是一种通用的编程语言吗?
    LabVIEW TCP/IP 断开重连问题
    LabVIEW 的bool(布尔)按键机械属性
    LabVIEW 远程控制VI
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/12251491.html
Copyright © 2020-2023  润新知