MySQL讲义第50讲——select 查询之查询练习(八):查询每门课程成绩前三名的学生信息


文章目录

  • MySQL讲义第50讲——select 查询之查询练习(八):查询每门课程成绩前三名的学生信息
  • 方法一
  • 方法二


以下查询使用到四张表,分别是:student、teacher、course 和 electives,表结构如下:

CREATE TABLE student(
    s_id char(5) primary key,
    s_name char(20),
    birth datetime,
    phone char(20),
    addr varchar(100)
);

INSERT INTO student
VALUES('S2011','张晓刚','1999-12-3','13163735775','信阳市'),
('S2012','刘小青','1999-10-11','13603732255','新乡市'),
('S2013','曹梦德','1998-2-13','13853735522','郑州市'),
('S2014','刘艳','1998-6-24','13623735335','郑州市'),
('S2015','刘岩','1999-7-6','13813735225','信阳市'),
('S2016','刘若非','2000-8-31','13683735533','开封市'),
('S2021','董雯花','2000-7-30','13533735564','开封市'),
('S2022','周华建','1999-5-25','13243735578','郑州市'),
('S2023','特朗普','1999-6-21','13343735588','新乡市'),
('S2024','奥巴马','2000-10-17','13843735885','信阳市'),
('S2025','周健华','2000-8-22','13788736655','开封市'),
('S2026','张学有','1998-7-6','13743735566','郑州市'),
('S2031','李明博','1999-10-26','13643732222','郑州市'),
('S2032','达芬奇','1999-12-31','13043731234','郑州市');

CREATE TABLE teacher(
    t_id char(5) primary key,
    t_name char(20),
    job_title char(20),
    phone char(20)
);

INSERT INTO teacher
VALUES('T8001','欧阳修','教授','13703735666'),
('T8002','华罗庚','教授','13703735888'),
('T8003','钟南山','教授','13703735675'),
('T8004','钱学森','教授','13703735638'),
('T8005','李白','副教授','13703735828'),
('T8006','孔子','教授','13703735457'),
('T8007','王安石','副教授','13703735369');

CREATE TABLE course(
    c_id char(4) primary key,
    c_name char(20),
    t_id char(5)
);

INSERT INTO course
VALUES('C101','古代文学','T8001'),
('C102','高等数学','T8002'),
('C103','线性代数','T8002'),
('C104','临床医学','T8003'),
('C105','传染病学','T8003'),
('C106','大学物理','T8004'),
('C107','诗歌欣赏','T8005'),
('C108','教育学','T8006'),
('C109','刑事诉讼法','T8007'),
('C110','经济法','T8007');

CREATE TABLE score(
    s_id char(5),
    c_id char(4),
    score int,
    primary key(s_id, c_id)
);

INSERT INTO score
VALUES('S2011','C102',84),('S2011','C105',90),('S2011','C106',79),('S2011','C109',65),
('S2012','C101',67),('S2012','C102',52),('S2012','C103',55),('S2012','C104',86),
('S2012','C105',87),('S2012','C106',64),('S2012','C107',62),
('S2012','C108',73),('S2012','C109',78),('S2012','C110',89),
('S2013','C102',97),('S2013','C103',68),('S2013','C104',66),('S2013','C105',68),
('S2014','C102',90),('S2014','C103',85),('S2014','C104',77),('S2014','C105',96),
('S2015','C101',69),('S2015','C102',66),('S2015','C103',88),('S2015','C104',69),
('S2015','C105',66),('S2015','C106',88),('S2015','C107',69),
('S2015','C108',66),('S2015','C109',88),('S2015','C110',69),
('S2016','C101',65),('S2016','C102',69),('S2016','C107',82),('S2016','C108',56),
('S2021','C102',72),('S2021','C103',90),('S2021','C104',90),('S2021','C105',57),
('S2022','C102',88),('S2022','C103',93),('S2022','C109',47),('S2022','C110',62),
('S2023','C102',68),('S2023','C103',86),('S2023','C109',56),('S2023','C110',91),
('S2024','C102',87),('S2024','C103',97),('S2024','C109',80),('S2024','C110',81),
('S2025','C102',61),('S2025','C105',62),('S2025','C106',87),('S2025','C109',82),
('S2026','C102',59),('S2026','C105',48),('S2026','C106',90),('S2026','C109',73);

方法一

思路:
(1)让 score 表中的每一行数据都和同一门课程并且比 score 大的分数连接。
(2)针对每个学生每门课的分数进行分组,统计比当前分数大的分数的个数,就是名次。

SELECT 
    sc1.s_id,
    s.s_name,
    sc1.c_id,
    c.c_name,
    sc1.score, 
    count(*) as rank
FROM 
    score sc1 JOIN student s
    ON sc1.s_id = s.s_id 
    JOIN course c
    ON c.c_id = sc1.c_id
    JOIN score sc2
    ON sc1.score <= sc2.score and sc1.c_id = sc2.c_id
GROUP BY 
    sc1.s_id, 
    sc1.c_id, 
    sc1.score
HAVING 
    count(*) <= 3
ORDER BY 
    sc1.c_id, 
    sc1.score DESC
;
+-------+-----------+------+-----------------+-------+------+
| s_id  | s_name    | c_id | c_name          | score | rank |
+-------+-----------+------+-----------------+-------+------+
| S2015 | 刘岩      | C101 | 古代文学        |    69 |    1 |
| S2012 | 刘小青    | C101 | 古代文学        |    67 |    2 |
| S2016 | 刘若非    | C101 | 古代文学        |    65 |    3 |
| S2022 | 周华建    | C102 | 高等数学        |    97 |    2 |
| S2013 | 曹梦德    | C102 | 高等数学        |    97 |    2 |
| S2014 | 刘艳      | C102 | 高等数学        |    90 |    3 |
| S2024 | 奥巴马    | C103 | 线性代数        |    97 |    1 |
| S2022 | 周华建    | C103 | 线性代数        |    93 |    2 |
| S2021 | 董雯花    | C103 | 线性代数        |    90 |    3 |
| S2021 | 董雯花    | C104 | 临床医学        |    90 |    1 |
| S2012 | 刘小青    | C104 | 临床医学        |    86 |    2 |
| S2014 | 刘艳      | C104 | 临床医学        |    77 |    3 |
| S2014 | 刘艳      | C105 | 传染病学        |    96 |    1 |
| S2011 | 张晓刚    | C105 | 传染病学        |    90 |    2 |
| S2012 | 刘小青    | C105 | 传染病学        |    87 |    3 |
| S2026 | 张学有    | C106 | 大学物理        |    90 |    1 |
| S2015 | 刘岩      | C106 | 大学物理        |    88 |    2 |
| S2025 | 周健华    | C106 | 大学物理        |    87 |    3 |
| S2016 | 刘若非    | C107 | 诗歌欣赏        |    82 |    1 |
| S2015 | 刘岩      | C107 | 诗歌欣赏        |    69 |    2 |
| S2012 | 刘小青    | C107 | 诗歌欣赏        |    62 |    3 |
| S2012 | 刘小青    | C108 | 教育学          |    73 |    1 |
| S2015 | 刘岩      | C108 | 教育学          |    66 |    2 |
| S2016 | 刘若非    | C108 | 教育学          |    56 |    3 |
| S2015 | 刘岩      | C109 | 刑事诉讼法      |    88 |    1 |
| S2025 | 周健华    | C109 | 刑事诉讼法      |    82 |    2 |
| S2024 | 奥巴马    | C109 | 刑事诉讼法      |    80 |    3 |
| S2023 | 特朗普    | C110 | 经济法          |    91 |    1 |
| S2012 | 刘小青    | C110 | 经济法          |    89 |    2 |
| S2024 | 奥巴马    | C110 | 经济法          |    81 |    3 |
+-------+-----------+------+-----------------+-------+------+
30 rows in set (0.00 sec)

方法二

SELECT
    sc2.s_id,
    s.s_name,
    sc2.c_id,
    c.c_name,
    sc2.rank
FROM
    student s JOIN
       (SELECT 
        sc.s_id,
        sc.c_id,
        sc.score, 
        (SELECT COUNT(*)
         FROM score sc1
         WHERE sc1.score >= sc.score AND sc1.c_id = sc.c_id) as rank
    FROM 
        score sc
    ORDER BY 
        sc.c_id, 
        sc.score DESC
    ) sc2 
    ON s.s_id = sc2.s_id 
    JOIN course c
    ON sc2.c_id = c.c_id
WHERE
    sc2.rank <= 3
;
+-------+-----------+------+-----------------+------+
| s_id  | s_name    | c_id | c_name          | rank |
+-------+-----------+------+-----------------+------+
| S2015 | 刘岩      | C101 | 古代文学        |    1 |
| S2012 | 刘小青    | C101 | 古代文学        |    2 |
| S2016 | 刘若非    | C101 | 古代文学        |    3 |
| S2013 | 曹梦德    | C102 | 高等数学        |    2 |
| S2022 | 周华建    | C102 | 高等数学        |    2 |
| S2014 | 刘艳      | C102 | 高等数学        |    3 |
| S2024 | 奥巴马    | C103 | 线性代数        |    1 |
| S2022 | 周华建    | C103 | 线性代数        |    2 |
| S2021 | 董雯花    | C103 | 线性代数        |    3 |
| S2021 | 董雯花    | C104 | 临床医学        |    1 |
| S2012 | 刘小青    | C104 | 临床医学        |    2 |
| S2014 | 刘艳      | C104 | 临床医学        |    3 |
| S2014 | 刘艳      | C105 | 传染病学        |    1 |
| S2011 | 张晓刚    | C105 | 传染病学        |    2 |
| S2012 | 刘小青    | C105 | 传染病学        |    3 |
| S2026 | 张学有    | C106 | 大学物理        |    1 |
| S2015 | 刘岩      | C106 | 大学物理        |    2 |
| S2025 | 周健华    | C106 | 大学物理        |    3 |
| S2016 | 刘若非    | C107 | 诗歌欣赏        |    1 |
| S2015 | 刘岩      | C107 | 诗歌欣赏        |    2 |
| S2012 | 刘小青    | C107 | 诗歌欣赏        |    3 |
| S2012 | 刘小青    | C108 | 教育学          |    1 |
| S2015 | 刘岩      | C108 | 教育学          |    2 |
| S2016 | 刘若非    | C108 | 教育学          |    3 |
| S2015 | 刘岩      | C109 | 刑事诉讼法      |    1 |
| S2025 | 周健华    | C109 | 刑事诉讼法      |    2 |
| S2024 | 奥巴马    | C109 | 刑事诉讼法      |    3 |
| S2023 | 特朗普    | C110 | 经济法          |    1 |
| S2012 | 刘小青    | C110 | 经济法          |    2 |
| S2024 | 奥巴马    | C110 | 经济法          |    3 |
+-------+-----------+------+-----------------+------+
30 rows in set (0.00 sec)