• 【DataBase】SQL45 Training 45题训练


    视频地址:

    https://www.bilibili.com/video/BV1pp4y1Q7Yv

    创建案例库:

    ------------创建数据库---------------
    create database data charset=utf8;
    
    ------------ 建表语句-----------------
    # 学生表 Student:
    create table Student(
    SId varchar(10) ,
    Sname varchar(10),
    Sage datetime,
    Ssex varchar(10));
    
    # 教师表 Teacher
    create table Teacher(
    TId varchar(10),
    Tname varchar(10)); 
    
    # 科目表 Course
    create table Course(
    CId varchar(10),
    Cname nvarchar(10),
    TId varchar(10)); 
    
    # 成绩表 SC
    create table SC(
    SId varchar(10),
    CId varchar(10),
    score decimal(18,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('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
    insert into Course values('01' , '语文' , '02'); 
    insert into Course values('02' , '数学' , '01'); 
    insert into Course values('03' , '英语' , '03'); 
    
    # 教师表 Teacher
    insert into Teacher values('01' , '张三');
    insert into Teacher values('02' , '李四'); 
    insert into Teacher values('03' , '王五'); 
    
    # 成绩表 SC
    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成绩高的学生信息和课程分数

    -- 一、教程解法 【0.018s】
    SELECT 
        a.sid,
        a.sname,
        a.sage,
        a.ssex,
        b.score as '课程01',
        c.score as '课程02'
    FROM
        student AS a
        INNER JOIN sc AS b ON a.sid = b.sid
        INNER JOIN sc AS c ON a.sid = c.sid AND b.cid = 01 AND c.cid = 02
    WHERE 
        b.score > c.score
    -- 二、我的解法 【0.019s】 
    SELECT
        D.sid,
        D.sname,
        D.sage,
        D.ssex,
        E.`课程01分数`,
        E.`课程02分数`
    FROM 
        student AS D,
        (
        SELECT
            A.sid,
            A.score AS '课程01分数',
            B.score AS '课程02分数'
        FROM 
            sc AS A,
            sc AS B 
        WHERE 
            A.sid = B.sid
            AND A.cid = 01
            AND B.cid = 02
            AND A.score > B.score
        ) AS E
    WHERE
        D.sid = E.sid

    1.1、要求查询同时存在01和02课程的情况

    用时【0.017s】

    SELECT 
        * 
    FROM 
        sc as a, 
        sc as b 
    WHERE 
        1 = 1
        AND a.sid = b.sid 
        AND a.cid = 01 
        AND b.cid = 02

    1.2、要求查询存在01, 可能存在02课程的情况(不存在显示为NULL)

    -- SQL解法1 【0.017s】
    SELECT 
        *
    FROM 
        (SELECT * FROM sc WHERE cid = 01) AS a
        LEFT JOIN sc AS b
        ON a.sid = b.sid
        AND b.cid = 02
    
    -- SQL解法2 【0.018s】
    SELECT 
        *
    FROM 
        sc AS a
        LEFT JOIN sc AS b
        ON a.sid = b.sid
        AND b.cid = 02
    WHERE 
        1 = 1
        AND a.cid = 01

    1.3、要求查询不存在01,存在02课程的情况’

    -- 解法1 【0.017s】会有多余记录
    SELECT 
        *
    FROM 
        (SELECT * FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid = 01)) AS a
        INNER JOIN sc AS b
        ON a.sid = b.sid
        AND b.cid = 02
    -- 解法2 【0.017s】
    SELECT
        *
    FROM 
        sc as a
    WHERE 
        1 = 1
        AND sid not in (SELECT sid FROM sc where cid = 01)
        AND cid = 02

    2、查询平均成绩大于60分的同学,学生编号和学生姓名和平均成绩

    耗时【0.018s】

    SELECT
        a.sid,
        a.sname,
        b.avg_score
    FROM 
        student as a,
        (SELECT sid,AVG(score) as avg_score FROM sc GROUP BY sid HAVING avg_score > 60) as b
    WHERE
        1 = 1
        AND a.sid = b.sid

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

    -- 我的解法 【0.016s】
    SELECT DISTINCT b.* FROM sc as a, student as b WHERE a.sid = b.sid
    
    -- 教程解法1 能够查出结果,但是SQL语法是有问题的,这是错误的示范
    SELECT
        b.*
    FROM
        sc AS a LEFT JOIN student AS b ON a.sid = b.sid
    GROUP BY b.sid
    --
    > 1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'devbase.b.Sname'
    which is not functionally dependent on columns in GROUP BY clause;
    this is incompatible with sql_mode=only_full_group_by
    --
    -- 教程解法2 GROUP BY 允许对指定的列查询 【0.016s】 SELECT b.* FROM (SELECT sid FROM sc GROUP BY sid) AS a LEFT JOIN student AS b ON a.sid = b.sid

    4、查询所有学生的编号,姓名,选课数,所有课程的总成绩。没选课程则成绩为NULL

    -- 首先在成绩表这里查询出选课数,和总成绩
    SELECT sid,COUNT(cid) AS course_count, SUM(score) total_score FROM sc GROUP BY sid
    
    -- 解法1 【0.018s】
    SELECT 
        a.sid,
        a.sname,
        b.course_count,
        b.total_score
    FROM
        student AS a 
        LEFT JOIN (SELECT sid,COUNT(cid) AS course_count, SUM(score) AS total_score FROM sc GROUP BY sid) AS b
        ON a.sid = b.sid;
        
    -- 解法2 教程可查出,实际操作不支持此语法
    SELECT
        a.sid,
        a.sname,
        COUNT(b.cid) AS '选课数',
        SUM(b.score) AS '总成绩'
    FROM
        student AS a
        LEFT JOIN sc AS b
        ON a.sid = b.sid
    GROUP BY a.sid
    --
    > 1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'devbase.a.Sname'
    which is not functionally dependent on columns in GROUP BY clause;
    this is incompatible with sql_mode=only_full_group_by
    --

    5、查询姓【李】的老师数量

    -- 我的解法【0.017s】
    SELECT count(tname) FROM teacher WHERE tname LIKE '李%'
    -- 教程解法【0.016s】
    SELECT count(1) FROM teacher WHERE tname LIKE '李%'

    6、查询学过【张三】老师课程的学生信息

    -- 我的解法,使用子查询作为逐个条件【0.017s】
    
    -- 用教师表的名字找tid
    SELECT tid FROM teacher WHERE tname = '张三'
    -- 用tid 给课程表找cid
    SELECT cid FROM course WHERE tid = 01
    -- 用cid 给成绩表找sid
    SELECT sid FROM sc WHERE cid = 02
    
    -- 最后用成绩表查出的sid作为in条件给学生表查询
    SELECT * FROM student WHERE sid IN (SELECT sid 
    FROM sc 
    WHERE cid = (
        SELECT cid 
        FROM course 
        WHERE tid = (
            SELECT tid 
            FROM teacher 
            WHERE tname = '张三'
        )
    ))
    
    -- 教程解法 耗时【0.016s】
    -- 1、老师和课程的关系
    SELECT A.*, B.tname FROM course A INNER JOIN teacher B ON A.tid = B.tid
    -- 2、教师和成绩的关系
    SELECT 
        * 
    FROM 
        SC a 
        INNER JOIN (SELECT b.*,c.tname FROM course b INNER JOIN teacher c ON b.tid = c.tid) d
        ON a.cid = d.cid 
    -- 3、得到学生和教师的关系
    SELECT 
        * 
    FROM
        student e
        INNER JOIN (
        SELECT 
            a.*,
            d.cname,
            d.tid,
            d.tname 
        FROM 
            SC a 
            INNER JOIN (SELECT b.*,c.tname FROM course b INNER JOIN teacher c ON b.tid = c.tid) d
            ON a.cid = d.cid 
        ) f
        ON e.sid = f.sid
    -- 4、追加老师等于张三的条件
    SELECT 
        * 
    FROM
        student e
        INNER JOIN (
        SELECT 
            a.*,
            d.cname,
            d.tid,
            d.tname 
        FROM 
            SC a 
            INNER JOIN (SELECT b.*,c.tname FROM course b INNER JOIN teacher c ON b.tid = c.tid) d
            ON a.cid = d.cid 
        ) f
        ON e.sid = f.sid
    WHERE f.tname = '张三'

    7、查询没有全选课程的学生

    -- 我的解法 耗时【0.018s】
    -- 首先筛选全部课程
    SELECT COUNT(1) FROM course
    -- 筛选SID
    SELECT 
        sid, 
        count(cid) course_count
    FROM 
        sc 
    GROUP BY sid
    HAVING course_count <> (SELECT COUNT(1) FROM course)
    
    -- 筛选学生
    SELECT A.*
    FROM student A, 
    (SELECT 
        sid, 
        count(cid) course_count
    FROM 
        sc 
    GROUP BY sid
    HAVING course_count <> (SELECT COUNT(1) FROM course)) B
    WHERE A.sid = B.sid
    
    -- 教程解法1 不支持的语法
    SELECT 
        *
    FROM
        student a
        LEFT JOIN sc b ON a.sid = b.sid
    GROUP BY a.sid
    HAVING COUNT(b.sid)    <> (SELECT COUNT(cid) FROM course)
    -- 教程解法2 语法也不支持
    SELECT
        a.*, b.*
    FROM
        sc a
        INNER JOIN student b
        ON a.sid = b.sid
    GROUP BY a.sid
    HAVING count(1) < (SELECT COUNT(1) FROM course)

    8、查询和学号01的同学,所学的课程至少同一个的学生

    -- 我的解法 解法1
    SELECT
        DISTINCT a.*
    FROM
        student a INNER JOIN sc b ON a.sid = b.sid
    WHERE
        1 = 1
        AND a.sid <> 01
        AND b.cid IN (SELECT cid FROM sc WHERE sid = 01)
    -- 解法2
    
    --  直接筛选
    SELECT 
        a.sid
    FROM 
        sc a 
    WHERE 
        a.cid in (SELECT cid FROM sc WHERE sid = '01') 
    GROUP BY a.sid
        
    -- 套student表子查询
    SELECT * FROM student WHERE sid IN (SELECT 
        a.sid
    FROM 
        sc a 
    WHERE 
        1 = 1
        AND a.cid in (SELECT cid FROM sc WHERE sid = '01') 
    GROUP BY a.sid)
        AND sid <> 01

    9、查询和01同学所选课程一样的其他同学

    解法没看懂。。。

    SELECT  *
    FROM student 
    WHERE student.sid IN(
        SELECT sid 
        FROM sc 
        WHERE 
            1 = 1
            AND sid <> 01 
            AND cid IN( SELECT cid FROM sc WHERE sid='01')
            GROUP BY sid HAVING COUNT(*) = (SELECT COUNT(*) FROM sc WHERE sid='01')
    )

    10、查询没学习过张三老师的任意一门课程的学生姓名

    -- 我的解法
    -- 1 张三老师ID
    SELECT tid 
    FROM teacher 
    WHERE tname = '张三'
    
    -- 2 张三老师所授课程ID
    SELECT cid 
    FROM course 
    WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')
    
    -- 3 学了该老师的课程的学生ID
    SELECT sid 
    FROM sc 
    WHERE cid IN(SELECT cid FROM course WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')) 
    
    -- 4、取反
    SELECT sname,sid 
    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 = '张三')))
    
    -- 教程解法
    -- 查出学习了张三老师课程的学生ID
    SELECT
        d.sid
    FROM
        sc a
        LEFT JOIN course b ON a.cid = b.cid
        LEFT JOIN teacher c ON b.tid = c.tid
        LEFT JOIN student d ON a.sid = d.sid 
    WHERE
        1 = 1
        AND c.tname = '张三'
    -- 取反
    SELECT sname,sid FROM student WHERE sid NOT IN(
        SELECT
            d.sid
        FROM
            sc a
            LEFT JOIN course b ON a.cid = b.cid
            LEFT JOIN teacher c ON b.tid = c.tid
            LEFT JOIN student d ON a.sid = d.sid 
        WHERE
            1 = 1
            AND c.tname = '张三'
    )

    11、查询两门以上不及格的学生

    -- 我的解法
    -- 1 在sc表直接查出sid和平均成绩【全条件筛查】
    SELECT sid, AVG(score) average_score 
    FROM sc 
    GROUP BY sid 
    HAVING 
        1 = 1
        AND COUNT(cid) > 1 
        AND average_score < 60
    -- 2 联表student查即可
    SELECT
        A.sname,
        B.*
    FROM
        student A,
        (
            SELECT sid, AVG(score) average_score 
            FROM sc 
            GROUP BY sid 
            HAVING 
                1 = 1
                AND COUNT(cid) > 1 
                AND average_score < 60
        ) B
    WHERE
        1 = 1
        AND A.sid = B.sid
    
    -- 教程解法 【语法不支持】
    -- 1、先求出两门以上不及格的学生ID
    SELECT 
        sid
        -- AVG(score) average_score
    FROM
        sc
    WHERE 
        1 = 1
        AND score < 60
    GROUP BY sid
    HAVING COUNT(1) > 1
    
    -- 求平均值的时候筛选我们要的同学
    SELECT
        a.sid,
        b.sname,
        AVG( score ) 
    FROM
        sc a
        LEFT JOIN student b ON a.sid = b.sid
        INNER JOIN ( SELECT sid FROM sc WHERE score < 60 GROUP BY sid HAVING COUNT( 1 ) > 1 ) c ON a.sid = c.sid 
    GROUP BY
        a.sid

    12、查询课程01小于60分,且降序排序的学生信息

    -- 我的解法,直接联表
    SELECT 
        -- a.sid,
        -- a.score,
        b.*
    FROM 
        sc a,
        student b
    WHERE 
        1 = 1 
        AND a.sid = b.sid
        AND a.score < 60 
        AND a.cid = 01
    ORDER BY a.score DESC
    
    -- 教程解法,左外连
    SELECT 
        -- a.sid,
        -- a.score,
        b.*
    FROM 
        sc a
        LEFT JOIN student b ON a.sid = b.sid
    WHERE 
        1 = 1 
        AND a.score < 60 
        AND a.cid = 01
    ORDER BY a.score DESC

    13、按平均成绩从高到底排序,显示所有学生所有课程成绩和平均成绩

    -- 我的解法
    -- sc表查询平均成绩和排序操作
    SELECT
        sid,
        AVG(score) avg_score
    FROM
        sc
    GROUP BY
        sid
    ORDER BY
        avg_score DESC
    -- 因为是所有学生,肯定是学生表做主表查询
    SELECT
        a.sid,
        a.sname,
        b.avg_score '平均分',
        (SELECT score FROM sc WHERE sid = a.sid AND cid = 01) '课程01',
        (SELECT score FROM sc WHERE sid = a.sid AND cid = 02) '课程02',
        (SELECT score FROM sc WHERE sid = a.sid AND cid = 03) '课程03'
    FROM
        student a
        LEFT JOIN (
            SELECT
            sid,
            AVG(score) avg_score
        FROM
            sc
        GROUP BY
            sid) b
        ON a.sid = b.sid
        ORDER BY
            `平均分` DESC -- 注意,这个排序要从子查询放到外面来
    
    -- 教程解法
    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

    14、查询各科成绩最高分,平均分,最低分

    按照如下形式:

    课程ID,课程名称,最高分,最低分,平均分,及格率,中等率,优良率,优秀率

    及格 >= 60

    中等 70 - 80

    优良 80 - 90

    优秀 >= 90 

    还要求选修人数,按这个人数降序排序

    人数相同,按课程号升序排序

    -- 我的解法
    SELECT 
        cid,  
        (SELECT cname FROM course WHERE cid = a.cid) '课程名称',
        MAX(score) '最高分', 
        ROUND(AVG(score), 2) '平均分', 
        MIN(score) '最低分', 
        (SELECT (SELECT COUNT(1) FROM sc WHERE cid = a.cid AND score > 59 ) / (SELECT COUNT(1) FROM sc WHERE cid = a.cid) ) '及格率',
        (SELECT (SELECT COUNT(1) FROM sc WHERE cid = a.cid AND score BETWEEN 70 AND 79 ) / (SELECT COUNT(1) FROM sc WHERE cid = a.cid) ) '中等率',
        (SELECT (SELECT COUNT(1) FROM sc WHERE cid = a.cid AND score BETWEEN 80 AND 89 ) / (SELECT COUNT(1) FROM sc WHERE cid = a.cid) ) '优良率',
        (SELECT (SELECT COUNT(1) FROM sc WHERE cid = a.cid AND score > 89 ) / (SELECT COUNT(1) FROM sc WHERE cid = a.cid) ) '优秀率',
        (SELECT COUNT(1) FROM sc WHERE cid = a.cid) '选修人数'
    FROM 
        sc a
    GROUP BY 
        cid 
    ORDER BY
        `选修人数` DESC, cid ASC
    
    -- 教程解法
    SELECT 
        cid,  
        -- (SELECT cname FROM course WHERE cid = a.cid) '课程名称',
        MAX(score) '最高分', 
        AVG(score) '平均分', 
        MIN(score) '最低分', 
        SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END) / COUNT(1)  AS '及格率',
        SUM(CASE WHEN score BETWEEN 70 AND 79 THEN 1 ELSE 0 END) / COUNT(1)  AS '中等率',
        SUM(CASE WHEN score BETWEEN 80 AND 89 THEN 1 ELSE 0 END) / COUNT(1)  AS '优良率',
        SUM(CASE WHEN score > 89 THEN 1 ELSE 0 END) / COUNT(1)  AS '优秀率',
        COUNT(1) '选修人数'
    FROM 
        sc a
    GROUP BY 
        cid 
    ORDER BY
        `选修人数` DESC, cid ASC

    15、按各科成绩进行排序,显示排名, 成绩重复继续排序

    -- 教程解法
    SELECT
        sid,
        cid,
        score,
        (@rank:= @rank + 1) rank-- 每查询到一行就赋值给这个记录进行叠加
    FROM
        sc, (SELECT @rank:=0) t -- 利用子查询做一张虚拟表,和sc表进行一个笛卡尔积
    ORDER BY
        score DESC

    16、查询学生的总成绩,进行排名

    -- 教程解法
    SELECT 
        a.*,
        @rank:= if(@sco=scos, '', @rank + 1) rank,
        -- @sco:= scos
    FROM
        (SELECT sid, SUM(score) scos FROM sc GROUP BY sid ORDER BY scos DESC) a,
        (SELECT @sco:= NULL, @rank:= 0) b        

    17、统计各科成绩各分数段人数:

    课程编号,课程名称

    [100 - 85)

    [85 - 70)

    [70 - 60)

    [60 - 0)

    和所占百分比

    SELECT
        cid,
        CONCAT( SUM( CASE WHEN score BETWEEN 0 AND 60 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(0 - 60]',
        CONCAT( SUM( CASE WHEN score BETWEEN 61 AND 70 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(60 - 70]',
        CONCAT( SUM( CASE WHEN score BETWEEN 71 AND 85 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(70 - 85]',
        CONCAT( SUM( CASE WHEN score BETWEEN 86 AND 100 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(85 - 100]' 
    FROM
        sc 
    GROUP BY
        cid

    补充其他字段:

    SELECT
        cid, 
        (SELECT cname FROM course WHERE cid = sc.cid) '课程',
        CONCAT( SUM( CASE WHEN score BETWEEN 0 AND 60 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(0 - 60]',
        SUM( CASE WHEN score BETWEEN 0 AND 60 THEN 1 ELSE 0 END ) 'P1',
        CONCAT( SUM( CASE WHEN score BETWEEN 61 AND 70 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(60 - 70]',
        SUM( CASE WHEN score BETWEEN 61 AND 70 THEN 1 ELSE 0 END ) 'P2',
        CONCAT( SUM( CASE WHEN score BETWEEN 71 AND 85 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(70 - 85]',
        SUM( CASE WHEN score BETWEEN 71 AND 85 THEN 1 ELSE 0 END ) 'P3',
        CONCAT( SUM( CASE WHEN score BETWEEN 86 AND 100 THEN 1 ELSE 0 END ) / COUNT( 1 ) * 100, '%' ) '(85 - 100]', 
        SUM( CASE WHEN score BETWEEN 86 AND 100 THEN 1 ELSE 0 END ) 'P4'
    FROM
        sc 
    GROUP BY
        cid

    18、查询各科前三名记录

    SELECT
        * 
    FROM
        sc a 
    WHERE
        ( SELECT count( 1 ) FROM sc b WHERE a.cid = b.cid AND a.score <= b.score ) < 4 
    ORDER BY
        a.cid,
        a.score DESC;

    19、查询每门课程被选修的学生人数

    SELECT
        cid,
        COUNT(1) '选修人数'
    FROM
        sc
    GROUP BY cid

    20、查询只是选修两门课程的学生学号和姓名

    -- 我的解法
    SELECT
        sid,
        (SELECT sname FROM student WHERE sid = sc.sid) 'name'
    FROM
        sc
    GROUP BY sid
    HAVING COUNT(cid) = 2
    
    -- 教程解法
    SELECT
        a.sid,
        b.sname,
        count(1) 'count'
    FROM
        sc a
        LEFT JOIN student b ON a.sid = b.sid
        GROUP BY a.sid, b.sname
        HAVING COUNT(a.cid) = 2

    21、查询男女人数

    SELECT ssex,COUNT(1) 'count' FROM student GROUP BY ssex

    22、查询名字中含有【风】的学生信息

    SELECT * FROM student WHERE sname LIKE "%%"

    23、查询同名同性学生并且统计人数

    -- 我的解法
    SELECT
        a.sname,
        a.ssex,
        COUNT(1) 'count'
    FROM
        student a,
        student b
    WHERE
        1 = 1
        AND a.sid <> b.sid
        AND a.sname = b.sname
        AND a.ssex = b.ssex
    GROUP BY a.sname, a.ssex
    
    -- 教程解法
    SELECT
        a.sname,
        a.ssex,
        COUNT(1) 'count'
    FROM
        student a
        INNER JOIN student b ON a.sid <> b.sid
        AND a.sname = b.sname
        AND a.ssex = b.ssex
    GROUP BY a.sname, a.ssex

    24、查询1990年出生的学生名单

    SELECT
        *
    FROM
        student
    WHERE
        YEAR(sage) = 1990

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

    SELECT
        cid,
        AVG(score) avg_score
    FROM
        sc
    GROUP BY cid
    ORDER BY avg_score DESC, cid ASC

    26、平均成绩大于等于85的所有学生学号,姓名,平均成绩

    -- 我的解法
    SELECT
        sid,
        (SELECT sname FROM student WHERE sid = sc.sid) 'name',
        AVG(score) avg_score
    FROM
        sc
    GROUP BY sid
    HAVING avg_score > 84
    
    
    -- 教程解法
    SELECT
        a.sid,
        b.sname,
        a.avg_score
    FROM
        (SELECT sid, AVG(score) avg_score FROM sc GROUP BY sid HAVING avg_score >= 85) a
        LEFT JOIN student b ON a.sid = b.sid

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

    -- 我的解法
    -- 1、筛查数学课程ID
    SELECT cid FROM course WHERE cname = '数学'
    -- 2 列查询 + 子查询 完成
    SELECT
        (SELECT sname FROM student WHERE sid = sc.sid) 'name',
        score
    FROM sc 
    WHERE 
        1 = 1
        AND cid = (SELECT cid FROM course WHERE cname = '数学') 
        AND score < 60
    
    -- 教程解法
    SELECT
        a.sid,
        b.sname,
        a.cid,
        a.score
    FROM
        sc a
        LEFT JOIN student b ON a.sid = b.sid
    WHERE 
        1 = 1
        AND cid = (SELECT cid FROM course WHERE cname = '数学')
        AND score < 60

    28、查询所有学生课程及分数情况【没有则NULL】

    SELECT
        a.sid,
        a.sname,
        b.cid,
        b.score
    FROM
        student a
        LEFT JOIN sc b ON a.sid = b.sid

    29、查询任意一门课程成绩在70分以上的学生名称,课程名称,分数

    -- 我的解法
    SELECT 
        (SELECT sname FROM student WHERE sid = sc.sid) 'name',
        (SELECT cname FROM course WHERE cid = sc.cid) 'course',
        score
    FROM
        sc
    WHERE score > 69
    
    -- 教程解法
    SELECT
        a.score,
        s.sname,
        c.cname
    FROM
        sc a
        LEFT JOIN course c ON a.cid = c.cid
        LEFT JOIN student s ON a.sid = s.sid
    WHERE a.score > 69

    30、查询存在不及格成绩的课程

    -- 我的解法
    SELECT
        DISTINCT cid
    FROM
        sc
    WHERE
        score < 60
    -- 教程解法
    SELECT
        cid, score
    FROM
        sc
    WHERE
        score < 60

    31、课程01成绩80分以上的学生ID和姓名

    -- 我的解法
    -- 1、成绩表筛查SID
    SELECT 
        sid
    FROM 
        sc
    WHERE
        1 = 1
        AND cid = 01 
        AND score > 79
    -- 2、联表
    SELECT
        a.sid,
        b.sname,
        a.score,
        a.cid
    FROM
        sc a
        INNER JOIN student b ON a.sid = b.sid
    WHERE
        1 = 1
        AND a.cid = 01
        AND a.score > 79

    32、每门课程的学生人数

    SELECT
        cid,
        COUNT( 1 ) 
    FROM
        sc 
    GROUP BY
        cid

    33、在成绩不重复的情况下,查询张三老师所授课程的学生中,成绩最高的学生信息和成绩

    -- 教程解法
    SELECT 
        *
    FROM
        sc a
        LEFT JOIN student b ON a.sid = b.sid
        LEFT JOIN course c ON a.cid = c.cid
        LEFT JOIN teacher d ON c.tid = d.tid
    WHERE
        1 = 1
        AND d.tname = '张三'
    ORDER BY a.score DESC
    LIMIT 1

    34、在成绩重复的情况下,查询张三老师所授课程的学生中,成绩最高的学生信息和成绩

    -- 我的解法
    
    -- 1、张三老师
    SELECT tid FROM teacher WHERE tname = '张三'
    -- 2、所受课程【可能不止一门】
    SELECT cid FROM course WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')
    -- 3、学习的学生
    SELECT * FROM sc WHERE cid IN (SELECT cid FROM course WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三'))
    -- 4、取最高成绩和ID
    SELECT * FROM sc WHERE cid IN (SELECT cid FROM course WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')) ORDER BY score DESC LIMIT 1 
    -- 5、连表 
    SELECT
        a.*,
        b.cid,
        (SELECT cname FROM course WHERE cid = b.cid),
        b.score
    FROM
        student a,
        (SELECT * FROM sc WHERE cid IN (SELECT cid FROM course WHERE tid = (SELECT tid FROM teacher WHERE tname = '张三')) ORDER BY score DESC LIMIT 1 ) b
    WHERE
        1 = 1
        AND a.sid = b.sid
        
    -- 教程解法
    SELECT
        s.*
    FROM
    (SELECT
        a.*,
        CASE 
            WHEN @score=score THEN @rank
            WHEN @score:=score THEN @rank:=@rank+1 
        END rn
    FROM
    (SELECT
        a.sid,
        a.score,
        b.sname,
        c.cid,
        d.tname
    FROM
        sc a
        LEFT JOIN student b ON a.sid = b.sid
        LEFT JOIN course c ON a.cid = c.cid
        LEFT JOIN teacher d ON c.tid = d.tid
    WHERE
        1 = 1
        AND d.tname = '张三') a,
    (SELECT @score:=NULL, @rank:=0) t ) s
    WHERE rn = 1

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

    -- 我的解法
    SELECT
        DISTINCT a.sid,
        a.cid,
        a.score
    FROM
        sc a,
        sc b
    WHERE
        1 = 1
        AND a.sid = b.sid
        AND a.score = b.score
        AND a.cid <> b.cid
    
    -- 教程解法
    SELECT
        a.sid,
        a.cid
    FROM
        sc a
        INNER JOIN sc b ON a.sid = b.sid
    WHERE
        a.score = b.score
        AND a.cid <> b.cid
    GROUP BY a.sid, a.cid

    36、查询每门课程考试最好的前两名

    -- 参考解法 https://blog.csdn.net/weixin_28847323/article/details/113088935
    SELECT
        * 
    FROM
        sc a 
    WHERE
        ( SELECT count( 1 ) FROM sc b WHERE a.cid = b.cid AND a.score <= b.score ) < 3 
    ORDER BY
        a.cid,
        a.score DESC;
    
    -- 教程解法
    SELECT
        sid,
        cid,
        score,
        rank
    FROM
        (SELECT 
            sc.*,
            @rank:=if(@c_cid=cid, if(@sco=score,@rank, @rank + 1), 1) rank,
            @sco:=score,
            @c_cid:=cid
        FROM
            sc,
            (SELECT @sco:=NULL, @rank:=0, @c_cid:=NULL) b
    ORDER BY cid, score DESC) a
    WHERE a.rank < 3

    37、查询每门课程的选修人数【超过五人统计】

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

    38、查询至少选修两门课程的学生ID  

    -- 我的解法
    SELECT 
        sid
    FROM
        sc
    GROUP BY
        sid
    HAVING
        COUNT(cid) > 1
        
    -- 教程解法
    SELECT 
        sid,
        COUNT(1) '选课数'
    FROM
        sc
    GROUP BY
        sid
    HAVING
        COUNT(1) >= 2

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

    -- 我的解法
    -- 1、全部课程
    SELECT COUNT(1) FROM course
    -- 2、全修了课程的sid
    SELECT
        sid
    FROM
        sc
    GROUP BY
        sid
    HAVING
        COUNT(cid) = (SELECT COUNT(1) FROM course)
    -- 3、做IN条件查询学生表
    SELECT * FROM student WHERE sid IN(
    SELECT
        sid
    FROM
        sc
    GROUP BY
        sid
    HAVING
        COUNT(cid) = (SELECT COUNT(1) FROM course))
        
    -- 教程解法1 [语法不支持]
    SELECT
        b.*,
        a.sid
    FROM
        sc a
        INNER JOIN student b ON a.sid = b.sid
    GROUP BY
        a.sid
    HAVING
        COUNT(1) = (SELECT COUNT(1) FROM course)
    
    -- 教程解法2 [笛卡尔积]
    SELECT a.* FROM student a 
    WHERE (SELECT COUNT(1) FROM sc b WHERE a.sid = b.sid) = (SELECT COUNT(1) FROM COURSE); 

    40、查询各个学生年龄,只按年份来算

    SELECT
        *,
        YEAR(NOW()) - YEAR(sage) age
    FROM
        student

    41、按照出生年月计算年龄,当前日月 < 出生年月的日月 年龄减一

    SELECT
        *,
        TIMESTAMPDIFF(YEAR,sage,NOW()) age
    FROM
        student

    42、查询本周过生日的学生

    SELECT *, WEEK(sage), WEEK(NOW()) FROM student 
    WHERE WEEK(sage) = WEEK( NOW() )

    43、查询下周过生日的学生

    SELECT *, WEEK(sage), WEEK(NOW()) FROM student 
    WHERE WEEK(sage) = WEEK( NOW() ) + 1

    44、查询本月过生日的学生

    SELECT *, MONTH(sage), MONTH(NOW()) FROM student 
    WHERE MONTH(sage) = MONTH( NOW() ) + 1

    45、查询下个月过生日的学生

    SELECT *, MONTH(sage), MONTH(NOW()) FROM student 
    WHERE MONTH(sage) = MONTH( NOW() ) + 1
  • 相关阅读:
    数据库连接池系列之——c3p0
    spring配置
    flume ng系列之——flume安装
    flume ng之组件介绍
    flume ng之TailSource
    Flume-NG + HDFS + HIVE日志收集分析
    flume+hadoop
    Flume+kafka+storm+hdfs
    IOS中坐标转换
    tabBarItem是模型,只有控件才有textColor属性
  • 原文地址:https://www.cnblogs.com/mindzone/p/14727364.html
Copyright © 2020-2023  润新知