MySQL:用一条SQL语句写成每个班级分数前三高的所有学生

用一条SQL语句写成每个班级分数前三高的所有学生:
stu表:
MySQL:用一条SQL语句写成每个班级分数前三高的所有学生_第1张图片

-- ----------------------------
-- Table structure for stu
-- ----------------------------
DROP TABLE IF EXISTS `stu`;
CREATE TABLE `stu`  (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `sname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `score` int(255) DEFAULT NULL,
  `classid` int(11) DEFAULT NULL,
  PRIMARY KEY (`sid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of stu
-- ----------------------------
INSERT INTO `stu` VALUES (1, 'Joe', 85, 1);
INSERT INTO `stu` VALUES (2, 'Henry', 80, 2);
INSERT INTO `stu` VALUES (3, 'Sam', 60, 2);
INSERT INTO `stu` VALUES (4, 'Max', 90, 1);
INSERT INTO `stu` VALUES (5, 'Janet', 69, 1);
INSERT INTO `stu` VALUES (6, 'Randy', 85, 1);
INSERT INTO `stu` VALUES (7, 'Will', 70, 1);
INSERT INTO `stu` VALUES (8, 'Chen', 85, 2);

SET FOREIGN_KEY_CHECKS = 1;

class表:
在这里插入图片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for class
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class`  (
  `cid` int(255) NOT NULL AUTO_INCREMENT,
  `cname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`cid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES (1, '1-101');
INSERT INTO `class` VALUES (2, '1-102');

SET FOREIGN_KEY_CHECKS = 1;

答案:

   select * from stu s,class
   where s.classid = class.cid 
   and score >= 
   (
      select distinct s1.score from stu s1 where s1.classid = class.cid
      order by s1.score desc limit 2,1
   )
   order by classid,score desc;

结果:
MySQL:用一条SQL语句写成每个班级分数前三高的所有学生_第2张图片

分析:
先查询前三高的分数(记得去重),然后降序排序(因为分数要从高到低),如果一个班级只有2个以内高的分数(不重复),那么limit会自动选择这2个或2个以内。有3个或者3个以上的高成绩(不重复),那么刚好以第3条记录为边界条件。
以边界条件(分数)查出来结果集后,使用classid(默认升序)和score进行排序。

另外在LeetCode上面有一个题跟这个非常相似,难度为困难
部门工资前三高的所有员工, 这上面有很多解法。
其中有一个解法比较容易理解:

SELECT e1.Salary 
FROM Employee AS e1
WHERE 3 > 
		(SELECT  count(DISTINCT e2.Salary) 
		 FROM	Employee AS e2 
	 	 WHERE	e1.Salary < e2.Salary 	AND e1.DepartmentId = e2.DepartmentId) ;

大意是Salary表进行自连,去重后如果比e1.Salary高的薪水小于3条(如果等于3条的话,是不需要进行比较的,因为如果高过我的有3个,说明我是第4个,一般满足前3位的count(DISTINCT e2.Salary) 结果是:0,1,2),那么e1.Salary本身就是满足前3名薪水这个条件的,就把本身这条记录留下来。
https://leetcode-cn.com/problems/department-top-three-salaries/solution/185-bu-men-gong-zi-qian-san-gao-de-yuan-gong-by-li/

你可能感兴趣的:(大数据分析,MySQL)