1-MySQL - SQL强化41题

before

最开始是41题,随着整理,貌似不止41题了,whatever,干就完了。

或者牛客网:https://www.nowcoder.com/exam/oj?tab=SQL篇&topicId=199&fromPut=pc_wzcpa_wxcarl_sf,由易到难跟着系列走

学生选课

准备数据:school.sql
-- mysql -uroot -p --default-character-set=utf8 <school.sql

DROP DATABASE IF EXISTS school;
CREATE DATABASE school CHARSET utf8;
USE school;
SET AUTOCOMMIT=0;
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `class`
-- ----------------------------
BEGIN;
INSERT INTO `class` VALUES ('1', '三年二班'), ('2', '三年三班'), ('3', '一年二班'), ('4', '二年九班');
COMMIT;

-- ----------------------------
--  Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '生物', '1'), ('2', '物理', '2'), ('3', '体育', '3'), ('4', '美术', '2');
COMMIT;

-- ----------------------------
--  Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `score`
-- ----------------------------
BEGIN;
INSERT INTO `score` VALUES ('1', '1', '1', '10'), ('2', '1', '2', '9'), ('5', '1', '4', '66'), ('6', '2', '1', '8'), ('8', '2', '3', '68'), ('9', '2', '4', '99'), ('10', '3', '1', '77'), ('11', '3', '2', '66'), ('12', '3', '3', '87'), ('13', '3', '4', '99'), ('14', '4', '1', '79'), ('15', '4', '2', '11'), ('16', '4', '3', '67'), ('17', '4', '4', '100'), ('18', '5', '1', '79'), ('19', '5', '2', '11'), ('20', '5', '3', '67'), ('21', '5', '4', '100'), ('22', '6', '1', '9'), ('23', '6', '2', '100'), ('24', '6', '3', '67'), ('25', '6', '4', '100'), ('26', '7', '1', '9'), ('27', '7', '2', '100'), ('28', '7', '3', '67'), ('29', '7', '4', '88'), ('30', '8', '1', '9'), ('31', '8', '2', '100'), ('32', '8', '3', '67'), ('33', '8', '4', '88'), ('34', '9', '1', '91'), ('35', '9', '2', '88'), ('36', '9', '3', '67'), ('37', '9', '4', '22'), ('38', '10', '1', '90'), ('39', '10', '2', '77'), ('40', '10', '3', '43'), ('41', '10', '4', '87'), ('42', '11', '1', '90'), ('43', '11', '2', '77'), ('44', '11', '3', '43'), ('45', '11', '4', '87'), ('46', '12', '1', '90'), ('47', '12', '2', '77'), ('48', '12', '3', '43'), ('49', '12', '4', '87'), ('52', '13', '1', '87'),('53', '13', '3', '88'),('54', '13', '4', '89');
COMMIT;

-- ----------------------------
--  Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('1', '男', '1', '理解'), ('2', '女', '1', '钢蛋'), ('3', '男', '1', '张三'), ('4', '男', '1', '张一'), ('5', '女', '1', '张二'), ('6', '男', '1', '张四'), ('7', '女', '2', '铁锤'), ('8', '男', '2', '李三'), ('9', '男', '2', '李一'), ('10', '女', '2', '李二'), ('11', '男', '2', '李四'), ('12', '女', '3', '如花'), ('13', '男', '3', '刘三'), ('14', '男', '3', '刘一'), ('15', '女', '3', '刘二'), ('16', '男', '3', '刘四');
COMMIT;

-- ----------------------------
--  Table structure for `teacher`
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `teacher`
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('1', '张磊老师'), ('2', '李平老师'), ('3', '刘海燕老师'), ('4', '朱云海老师'), ('5', '李杰老师');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
表关系:

开始吧!

查询大于60分的成绩
SELECT
  num
FROM
  score
WHERE num > 60 ORDER BY num DESC;
查询每门课程及对应的老师姓名
SELECT
  course.cname,
  teacher.tname
FROM
  course
  INNER JOIN teacher
    ON course.cid = teacher.tid;
查询学生及学生所在的班级
SELECT
  student.sname,
  class.caption
FROM
  student
  LEFT JOIN class
    ON student.class_id = class.cid;
查询每个班级及每个班级学生人数和数量
SELECT
  class.caption,
  COUNT(student.sname),
  GROUP_CONCAT(student.sname)
FROM
  student
  LEFT JOIN class
    ON student.class_id = class.cid
GROUP BY class.caption;
查询男生和女生的个数及对应的学生姓名
SELECT
  gender,
  COUNT(gender),
  GROUP_CONCAT(sname)
FROM
  student
GROUP BY gender;
查询每个学生所学的课程名称
SELECT
  student.sname,
  GROUP_CONCAT(course.cname)
FROM
  student
  RIGHT JOIN score
    ON student.sid = score.student_id
  LEFT JOIN course
    ON score.course_id = course.cid
GROUP BY sname;
查询每个同学每门课的成绩
SELECT
  student.sname,
  course.cname,
  score.num
FROM
  student
  LEFT JOIN score
    ON student.sid = score.sid
  LEFT JOIN course
    ON score.course_id = course.cid;
查询平均成绩大于60分的同学的学号(sid)和平均成绩
-- 有两种解题思路,第一种就是先联表,在过滤条件
SELECT
  student.sname,
  AVG(score.num) AS '平均成绩'
FROM
  student
  LEFT JOIN score
    ON student.sid = score.student_id
GROUP BY student.sname
HAVING AVG(score.num) > 60;

-- 第二种就是先使用子查询,再联表,各有优势吧
SELECT
  student.sname,
  tmp.avg_num
FROM
  student
  RIGHT JOIN
    (SELECT
      student_id,
      AVG(num) AS avg_num
    FROM
      score
    GROUP BY student_id
    HAVING AVG(num) > 60) AS tmp
    ON student.sid = tmp.student_id
ORDER BY tmp.avg_num;
查询所有同学的学号(sid),姓名,选课数和总成绩
SELECT
  student.sid,
  student.sname,
  COUNT(score.course_id) AS '选课数',
  SUM(score.num) AS '总成绩'
FROM
  student
  RIGHT JOIN score
    ON student.sid = score.student_id
GROUP BY score.student_id;
查询姓 "李" 的老师的个数
SELECT
  COUNT(1)
FROM
  teacher
WHERE tname LIKE '李%';
查询没有选择 "李平老师" 课程的学生姓名和学号(sid)
-- 解题思路是:先看 "李平老师" 教授了哪些课程,并且拿到课程 id
SELECT
  teacher.tname,
  course.cname,
  course.cid
FROM
  teacher
  LEFT JOIN course
    ON teacher.tid = course.teacher_id
WHERE teacher.tname = '李平老师';

-- 根据课程 id ,去 score 表过滤出学习了 "李平老师" 课程的学生的 sid
SELECT
  student_id
FROM
  score
WHERE course_id IN
  (SELECT
    course.cid
  FROM
    teacher
    LEFT JOIN course
      ON teacher.tid = course.teacher_id
  WHERE teacher.tname = '李平老师')
GROUP BY student_id;     -- 因为有人或者学生有重名的,所以分组过滤以下


-- 有了学生的sid,就可以去 student 表中 not in 一下就行了
SELECT
  sid,
  sname
FROM
  student
WHERE sid NOT IN
  (SELECT
    student_id
  FROM
    score
  WHERE course_id IN
    (SELECT
      course.cid
    FROM
      teacher
      LEFT JOIN course
        ON teacher.tid = course.teacher_id
    WHERE teacher.tname = '李平老师')
  GROUP BY student_id);
查询 "生物" 课程比 "物理" 课程成绩高的所有学生的姓名
-- 方法一,解题思路是:先分别获取 "生物" 和 "物理" 课程的成绩
SELECT
  score.student_id,
  course.cname,
  score.num
FROM
  course
  LEFT JOIN score
    ON course.cid = score.course_id
WHERE course.cname = "生物";


SELECT
  score.student_id,
  course.cname,
  score.num
FROM
  course
  LEFT JOIN score
    ON course.cid = score.course_id
WHERE course.cname = "物理";

-- 再拼成一个 student_id 生物 生物成绩 物理 物理成绩  这样的一张表,再根据成绩过滤,此时的表已经有了符合条件的sid
SELECT
  A.student_id AS sid
FROM
  (SELECT
    score.student_id,
    course.cname,
    score.num
  FROM
    course
    LEFT JOIN score
      ON course.cid = score.course_id
  WHERE course.cname = "生物") AS A
  INNER JOIN
    (SELECT
      score.student_id,
      course.cname,
      score.num
    FROM
      course
      LEFT JOIN score
        ON course.cid = score.course_id
    WHERE course.cname = "物理") AS B
    ON A.student_id = B.student_id
WHERE A.num > B.num;

-- 根据 sid 再去联 学生表 取出 学生姓名
SELECT
  student.sid,
  student.sname,
  C.biology,
  C.biology_score,
  C.physics,
  C.physics_score
FROM
  student
  INNER JOIN
    (SELECT
      A.student_id AS sid,
      A.cname AS biology,
      A.num AS biology_score,
      B.cname AS physics,
      B.num AS physics_score -- 为了结果好看,多提取了几个字段
     FROM
      (SELECT
        score.student_id,
        course.cname,
        score.num
      FROM
        course
        LEFT JOIN score
          ON course.cid = score.course_id
      WHERE course.cname = "生物") AS A
      INNER JOIN
        (SELECT
          score.student_id,
          course.cname,
          score.num
        FROM
          course
          LEFT JOIN score
            ON course.cid = score.course_id
        WHERE course.cname = "物理") AS B
        ON A.student_id = B.student_id
    WHERE A.num > B.num) AS C
    ON student.sid = C.sid;

-- 方法二,思路是,先单独从course表中过滤物理和生物课程的id
-- 再从score表中根据课程id过滤出来学习过这两门课的学生,并且进行联表(联表的目的是便于比较成绩)使用where过滤
-- 此时有了符合条件的记录,然后再与学生表联接,得到最终的学生名称
SELECT
  student.sid,
  student.sname,
  C.biology_score,
  C.physics_score
FROM
  student
  INNER JOIN
    (SELECT
      A.student_id,
      A.num AS biology_score,
      B.num AS physics_score
    FROM
      (SELECT
        student_id,
        num
      FROM
        score
      WHERE course_id IN
        (SELECT
          course.cid
        FROM
          course
        WHERE cname = "生物")) AS A
      INNER JOIN
        (SELECT
          student_id,
          num
        FROM
          score
        WHERE course_id IN
          (SELECT
            course.cid
          FROM
            course
          WHERE cname = "物理")) AS B
        ON A.student_id = B.student_id
    WHERE A.num > B.num) AS C
    ON student.sid = C.student_id;
查询学过 "001" and "002" 课程的同学的姓名
-- 方法1
SELECT
  student.sid,
  student.sname
FROM
  student
  INNER JOIN score
    ON student.sid = score.student_id
WHERE score.course_id = 1
  OR score.course_id = 2
GROUP BY score.student_id
HAVING COUNT(score.course_id) > 1;

-- 方法2,使用union all 优化 or 语句
SELECT
  student.sid,
  student.sname
FROM
  student
  INNER JOIN
    (SELECT
      student_id
    FROM
      score
    WHERE course_id = 1
    UNION
    ALL
    SELECT
      student_id
    FROM
      score
    WHERE course_id = 2) AS A
    ON student.sid = A.student_id
GROUP BY A.student_id
HAVING COUNT(A.student_id) > 1;
查询学过 "李平老师" 教授的所有课程的学生姓名
SELECT
  student.sid,
  student.sname
FROM
  student
  RIGHT JOIN
    (-- 这里一定要用右联接,左联接的话会将不符合条件的学生也返回
     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
    HAVING COUNT(course_id) =
      (SELECT
        COUNT(cid)
      FROM
        course
        LEFT JOIN teacher
          ON course.teacher_id = teacher.tid
      WHERE teacher.tname = "李平老师")) AS A
    ON student.sid = A.student_id;
查询课程编号 "002" 的学生成绩比课程编号 "001" 的学生成绩低的同学的姓名
-- 法1
SELECT
  student.sid,
  student.sname,
  C.one,
  C.two
FROM
  student
  RIGHT JOIN
    (SELECT
      A.student_id,
      A.num AS ONE,
      B.num AS two
    FROM
      (SELECT
        *
      FROM
        score
      WHERE course_id IN
        (SELECT
          cid
        FROM
          course
        WHERE cid = 1)) AS A
      INNER JOIN
        (SELECT
          *
        FROM
          score
        WHERE course_id IN
          (SELECT
            cid
          FROM
            course
          WHERE cid = 2)) AS B
        ON A.student_id = B.student_id) AS C
    ON student.sid = C.student_id
WHERE ONE > two;

-- 法2
SELECT
  sid,
  sname
FROM
  student
WHERE sid IN
  (SELECT
    t1.student_id
  FROM
    (SELECT
      num num2,
      student_id
    FROM
      score
    WHERE course_id = 2) t2
    INNER JOIN
      (SELECT
        student_id,
        num num1
      FROM
        score
      WHERE course_id = 1) t1
      ON t1.student_id = t2.student_id
  WHERE num2 < num1);
查询成绩小于60分的学生姓名和成绩
SELECT
  student.sid,
  student.sname
FROM
  student
WHERE sid IN -- 再 in 的时候,就去重了,也可以使用分组或者distinct去重
   (SELECT
    student_id -- 因为有多门成绩,所以,学生id是有重复的
   FROM
    score
  WHERE num < 60);

-- 使用分组
SELECT
  student.sid,
  student.sname
FROM
  student
WHERE sid IN
  (SELECT
    student_id
  FROM
    score
  WHERE num < 60
  GROUP BY student_id);

-- 使用distinct和联表
SELECT
  student.sid,
  student.sname
FROM
  student
  RIGHT JOIN
    (SELECT DISTINCT
      student_id -- 但是 distinct 效率不高
     FROM
      score
    WHERE num < 60) AS A
    ON student.sid = A.student_id
查询没有选择学习全部课程的学生的姓名
-- 法1 使用 in 
SELECT
  sid,
  sname
FROM student WHERE sid IN
(SELECT
  student_id
FROM
  score
GROUP BY student_id
HAVING COUNT(student_id) !=
  (SELECT
    COUNT(cid)
  FROM
    course));

-- 法2,使用 连表
SELECT
  student.sid,
  student.sname
FROM
  student
  RIGHT JOIN
    (SELECT
      student_id
    FROM
      score
    GROUP BY student_id
    HAVING COUNT(student_id) !=
      (SELECT
        COUNT(cid)
      FROM
        course)) AS A
ON student.sid=A.student_id;
查询至少有一门课是和学生 "001" 选择的课程是一样的学生姓名
-- 1. 先要知道 001 这个学生所有学过的课程 id
SELECT
  course_id
FROM
  score
WHERE student_id = 1;

-- 2. 找学生001以外的学生学过的课程,只要有一门和学生001重合就是我们想要的结果
SELECT
  *
FROM
  student
WHERE sid IN     -- 使用 in 其实子查询中可以不用分组的
  (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);
查询和学生 "003" 选择的课程完全一样的学生姓名
--------------- 法1 ----------------
-- 思路是先知道学生 003 选择了哪些课程,并且,为了方便,将 003 选择的所有课程使用 group_concat 进行拼接
-- 后续的判断对比拼接后字符串,算是一种取巧的行为
SELECT student_id,GROUP_CONCAT(course_id) FROM score WHERE student_id=3;
+------------+-------------------------+
| student_id | GROUP_CONCAT(course_id) |
+------------+-------------------------+
|          3 | 1,2,3,4                 |
+------------+-------------------------+
1 row in set (0.00 sec)

-- 然后,同样使用 group_concat 拼接出来其他同学的课程id,和 003 的拼接字符串对比
SELECT
  student.sid,
  student.sname,
  A.course_list
FROM
  student
  INNER JOIN
    (SELECT
      student_id,
      GROUP_CONCAT(course_id) AS course_list
    FROM
      score
    WHERE student_id != 3 -- 先把 003 这个家伙排除出去
     GROUP BY student_id
    HAVING GROUP_CONCAT(course_id) =
      (SELECT
        GROUP_CONCAT(course_id)
      FROM
        score
      WHERE student_id = 3)) AS A
    ON student.sid = A.student_id;
+-----+--------+-------------+
| sid | sname  | course_list |
+-----+--------+-------------+
|   4 | 张一   | 1,2,3,4     |
|   5 | 张二   | 1,2,3,4     |
|   6 | 张四   | 1,2,3,4     |
|   7 | 铁锤   | 1,2,3,4     |
|   8 | 李三   | 1,2,3,4     |
|   9 | 李一   | 1,2,3,4     |
|  10 | 李二   | 1,2,3,4     |
|  11 | 李四   | 1,2,3,4     |
|  12 | 如花   | 1,2,3,4     |
+-----+--------+-------------+
9 rows in set (0.00 sec)


--------------- 法2 ----------------
-- 首先拿到 003 学生 学过的课程 id 结果得到 1 2 3 4
SELECT * FROM score WHERE student_id = 3;  
SELECT COUNT(1) FROM score WHERE student_id = 3;   -- 得到结果 4 门课

-- 排除 001 学生,但其他学生选择的课程还需要处理
SELECT student_id FROM score WHERE student_id != 3 GROUP BY student_id;  -- 排除 003 后的其他学生,因为课程有门,学生id由重复,这里使用分组去重


-- 过滤出来和 001 学生选课门数一样的学生,每个同学的选课数量必须和 001 选择的课程数量相等
SELECT student_id FROM score WHERE student_id != 3 GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(1) FROM score WHERE student_id = 3); 

-- 虽然选课数量相等,但选择的课程可能不一样,所以再次根据课程id去判断
SELECT student_id FROM score WHERE student_id !=3 AND student_id IN (
  SELECT student_id FROM score WHERE student_id != 1 GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(1) FROM score WHERE student_id = 3)
) AND course_id IN (   -- in 这一步判断的是保证其他学生和 003 选择的课程一样
  SELECT course_id FROM score WHERE student_id = 3  
) GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(1) FROM score WHERE student_id = 3);

-- 最后,再根据 student_id获取学生的姓名,这里用的in,也可以使用连表
SELECT sid,sname FROM student WHERE sid IN (   -- 获取学生姓名
SELECT student_id FROM score WHERE student_id !=3 AND student_id IN (
  SELECT student_id FROM score WHERE student_id != 1 GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(1) FROM score WHERE student_id = 3)
) AND course_id IN (   -- in 这一步判断的是保证其他学生和 003 选择的课程一样
  SELECT course_id FROM score WHERE student_id = 3  
) GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(1) FROM score WHERE student_id = 3)
);
+-----+--------+
| sid | sname  |
+-----+--------+
|   4 | 张一   |
|   5 | 张二   |
|   6 | 张四   |
|   7 | 铁锤   |
|   8 | 李三   |
|   9 | 李一   |
|  10 | 李二   |
|  11 | 李四   |
|  12 | 如花   |
+-----+--------+
9 rows in set (0.01 sec)
按平均成绩从高到低显示各科成绩,按如下形式显示: 学生ID、学生姓名、各科成绩(如:语文,英语,数学)、考了几科、平均分
SELECT 
  current_student.`sid`,
  current_student.`sname`,
  (SELECT num FROM score LEFT JOIN course ON score.`course_id`=course.`cid` WHERE course.`cname`='生物' AND score.`student_id`=current_student.`sid`) AS '生物',
  (SELECT num FROM score LEFT JOIN course ON score.`course_id`=course.`cid` WHERE course.`cname`='物理' AND score.`student_id`=current_student.`sid`) AS '物理',
  (SELECT num FROM score LEFT JOIN course ON score.`course_id`=course.`cid` WHERE course.`cname`='体育' AND score.`student_id`=current_student.`sid`) AS '体育',
  (SELECT num FROM score LEFT JOIN course ON score.`course_id`=course.`cid` WHERE course.`cname`='美术' AND score.`student_id`=current_student.`sid`) AS '美术',
  (SELECT COUNT(num) FROM score WHERE student_id=current_student.sid) AS '考了几科',
  IF ((SELECT SUM(num)/4 FROM score WHERE student_id=current_student.sid GROUP BY student_id), (SELECT SUM(num)/4 FROM score WHERE student_id=current_student.sid GROUP BY student_id), 0) AS '平均分'
FROM student AS current_student LEFT JOIN  score
ON score.`student_id`=current_student.`sid`
LEFT JOIN course
ON course.cid=score.course_id
GROUP BY current_student.sid
ORDER BY (SELECT SUM(num)/4 FROM score WHERE student_id=current_student.sid GROUP BY student_id) DESC;
查询各科成绩最高分和最低分:以如下形式显示:课程ID,最高分,最低分;如果最低分小于60,显式 "再接再励"
SELECT course_id,MAX(num),MIN(num) FROM score GROUP BY course_id;

SELECT 
  course_id,MAX(num) AS '最高分',
  CASE WHEN MIN(num) < 60 THEN "再接再励" ELSE MIN(num) END AS '最低分'
FROM score 
GROUP BY course_id;





















删除 score 表 "李平老师" 相关记录
EXPLAIN DELETE FROM score WHERE	course_id IN (
SELECT cid FROM course WHERE teacher_id IN (
SELECT tid FROM teacher WHERE tname='李平老师'));

查询与学号为"2"的同学选课程完全相同的其他 学生学号和姓名
-- 首先知道学号为"2"的同学的选课是什么,好跟后面的SQL语句做对比。
SELECT 
	student.sid,
	student.sname,
	GROUP_CONCAT(course.cname)
FROM score
LEFT JOIN course ON score.course_id=course.cid
LEFT JOIN student ON score.student_id=student.sid
WHERE student.sid=2
GROUP BY student.sid;
+------+-------+----------------------------+
| sid  | sname | GROUP_CONCAT(course.cname) |
+------+-------+----------------------------+
|    2 | 钢蛋  | 生物,体育,美术             |
+------+-------+----------------------------+

-- 然后再写SQL
SELECT 
	student.sid,
	student.sname,
	GROUP_CONCAT(course.cname)
FROM score
LEFT JOIN course ON score.course_id=course.cid
LEFT JOIN student ON score.student_id=student.sid
WHERE
	score.course_id in (SELECT course_id FROM score WHERE student_id=2)
	AND score.student_id in (SELECT student_id from score WHERE student_id != 2 GROUP BY student_id HAVING COUNT(1)=(SELECT COUNT(1) FROM score WHERE student_id=2))
GROUP BY
	score.student_id
HAVING
	COUNT(1)=(SELECT COUNT(1) FROM score WHERE student_id=2);
+------+-------+----------------------------+
| sid  | sname | GROUP_CONCAT(course.cname) |
+------+-------+----------------------------+
|   13 | 刘三  | 体育,生物,美术             |
+------+-------+----------------------------+

that's all,see also:

武sir41题原出处
景女神41题前15题及答案参考 | 景女神41题后25题及答案参考
小马哥41题及答案

posted @ 2020-09-24 11:58  听雨危楼  阅读(361)  评论(0编辑  收藏  举报