SQL-去除最大值与最小值求均值的问题
- 背景
今天有同事问我一道关于数据库SQL的面试题,我刚开始随便给了一个思路,后来思索发现这个思路有漏洞,于是总结下来,仅供参考。
问题: 薪水表中是员工薪水的基本信息,包括雇员编号,和薪水,查询除去最高、最低薪水后的平均薪水。
- 一、薪水表信息
CREATE TABLE `salaries` (
`emp_no` int NOT NULL,
`salary` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
测试数据如下:
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10003, 6000);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10004, 6000);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10001, 6000);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10006, 6100);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10005, 6900);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (10008, 7100);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100010, 7400);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100013, 7500);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100014, 7500);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100015, 7688);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100018, 8000);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100020, 8100);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100028, 8200);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100026, 8400);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100035, 8500);
INSERT INTO `salaries`(`emp_no`, `salary`) VALUES (100038, 8500);
- 二、查询分析
思路1、最容易想到的方法,就是查询到薪水的最大值和最小值。然后从薪水中排除掉这两个,计算平均值即可。
select avg(salary)
from salaries
where salary not in (
(select min(salary) from salaries),
(select max(salary) from salaries)
) ;
思路2、使用开窗函数Max() Over() 和 Min() Over() 求出最大值,然后排除掉这两个,再计算平均值。
select
avg(salary)
from (
select emp_no,salary, min(salary) over() min_sal, max(salary) over() max_sal from salaries
) x
where salary not in (min_sal,max_sal) ;
思路3 、直接使用数学方法,平均值 = (求和-最大值-最小值)/ (总个数-2)
select (sum(salary)-min(salary)-max(salary))/(count(*)-2)
from salaries ;
思路4、使用一次row_number() over 窗口函数和count() over 函数,count窗口函数统计表中所有记录数,使用row_number窗口函数按照薪水升序排列,排序结果 = 1 即为最小值,排序结果 = count出的结果 即为最大值。
select
avg(salary)
from
(
select
emp_no,
salary,
count(*) over() num ,
row_number() over(order by salary asc) rn
from salaries ) T
where rn <> 1 and rn <> num ;
说明:
count(*)over() 求总计数,
count(*)over(order by A...) 递加求计数,
count(*)over(partition by A...) 分组求计数,
count(*)over(partition by A...order by b...) 分组递加求计数
查询看下这四个统计结果

思路5、使用两次row_number() over 窗口函数,一个按照薪水升序,一个按照薪水降序,过滤掉第一个即去掉最大值和最小值。
select
avg(salary)
from
(
select
emp_no,
salary,
row_number() over(order by salary desc) rn_desc,
row_number() over(order by salary asc) rn_asc
from salaries ) T
where rn_desc > 1 and rn_asc > 1 ;
总结: 我们在执行这5个SQL语句后,会发现统计出的平均值不一样,原因就在于:薪水表中最高薪水的人和最低薪水的人都不止一个。
前2个思路会将所有最高薪水和最低薪水全部去除,求得平均值。然而,思路3、4、5都只是去除一个最高薪水和一个最低薪水,然后求平均值。所以才导致计算出的结果不一致。
SQL-去除最大值与最小值求均值的问题的更多相关文章
- Java初学者作业——编写 Java 程序,用户输入 3 个操作数,分别求出最大值、最小值和平均值。
返回本章节 返回作业目录 需求说明: 编写 Java 程序,用户输入 3 个操作数,分别求出最大值.最小值和平均值. 实现思路: 定义 Java 类,定义 3 个方法,用来求 3 个数字的最大值.最小 ...
- Java开发中经典的小实例-(比较输入数值的最大值、最小值和平均值)
//输入数字个数来产生数字并且比较大小 import java.util.Scanner;public class Test1 { public static void main(String ...
- Java对二叉搜索树进行插入、查找、遍历、最大值和最小值的操作
1.首先,须要一个节点对象的类.这些对象包括数据.数据代表存储的内容,并且还有指向节点的两个子节点的引用 class Node { public int iData; public double dD ...
- 不需要sql进行计算数据的平均值、最大值、最小值、和
介绍下SqlServer.前端js.后台C#三个阶段对均值.最大值.最小值.和计算int[] jisuan = {0, 1, 3, 5, 7,8 }; List<int> jisuan2 ...
- POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 53703 Accepted: 25237 ...
- JS创建一个数组1.求和 2.求平均值 3.最大值 4.最小值 5.数组逆序 6.数组去重 0.退出
rs = require("readline-sync"); let arr = []; console.log("请输入数组的长度:"); let arr_l ...
- Jsの数组练习-求一组数中的最大值和最小值,以及所在位置
要求:求一组数中的最大值和最小值,以及所在位置 代码实现: <!DOCTYPE html> <html lang="en"> <head> &l ...
- C语言:用指针求最大值和最小值
用指针求数组最大值和最小值(10分) 题目内容: 用指针求含有十个元素的数组最大值和最小值 主函数参考 int main() { int a[10],i,maxnum,minnum; for(i=0; ...
- Java求一个数组中的最大值和最小值
原创作品,转载请注明出处:https://www.cnblogs.com/sunshine5683/p/9927186.html 今天在工作中遇到对一个已知的一维数组取出其最大值和最小值,分别用于参与 ...
- java从键盘输入若干数,求其最大值,最小值,平均值。等等
总结:有一定基础的人,应该发现第一个程序可以运行,其实它有个致命的错误.有谁能一眼看出来呢?第二个程序是对的. 这个题目求最大值,最小值,平均值我不会求,不知道这个if判断放在类的外面还是main函数 ...
随机推荐
- 【Docker】Harbor 分布式仓库管理
一.Harbor 介绍 Harbor 是 VMware 公司开源的企业级 Docker Registry 项目,其目标是帮助用户迅速搭建一个企业级的 Docker Registry (私有仓库)服务. ...
- 使用 Sa-Token 完成踢人下线功能
一.需求 在企业级项目中,踢人下线是一个很常见的需求,如果要设计比较完善的话,至少需要以下功能点: 可以根据用户 userId 踢出指定会话,对方再次访问系统会被提示:您已被踢下线,请重新登录. 可以 ...
- Python获取jsonp数据
使用python爬取数据时,有时候会遇到jsonp的数据格式,由于不是json的,所以不能直接使用json.loads()方法来解析,需要先将其转换为json格式,再进行解析.在前面讲了jsonp的原 ...
- 2020-09-06:Docker的命名空间有哪些?
福哥答案2020-09-06: 福哥口诀法:命进I网挂U用 1.进程命名空间.CLONE_NEWPID.进程编号. 2.IPC 命名空间.CLONE_NEWPIPC.信号量.消息队列何共享内存. 3. ...
- Docker入门与实战-Docker镜像的使用
Docker入门与实战 二.Docker镜像的使用 1.获取镜像 命令:docker [image] pull image-name[:tag] 说明: name为镜像仓库名称,严格来说, ...
- Vue3.3 的新功能的一些体验
Vue3 在大版本 3.3 里面推出来了一些新功能(主要是语法糖),网上有各种文章,但是看起来似乎是一样的. 我觉得吧,有新特性了,不能光看,还要动手尝试一下. DefineOptions 宏定义 先 ...
- 禁用input自动补全,模拟type=password输入字符显示为星号
最近遇到一个想禁用浏览器的密码自动补全的功能,翻遍了整个技术论坛大多使用用auto-complete="new-password"但是本人测试不怎么管用,所有又找到了如下几种方法, ...
- [ 基于宝塔部署 ] 恋爱博客 -- Like_Girl 5.0
1)环境准备 云服务器 [ CentOS 7 ] 域名解析 love.daxiaoba.cool 宝塔面板 yum install -y wget && wget -O install ...
- 闺蜜机 StanbyME 产品随想
今天媳妇告诉我,现在小度这边推出一款叫 "闺蜜机"的可用移动的IPAD设备,我点开链接一看,就感觉兴趣不大,不就是一款把屏幕做的更大些的IPAD了吗? 有哪些更多创新呢?为什么会需 ...
- Instruments中常用Template的使用
Instruments是苹果提供的Xcode套件,可用于分析iOS,MacOS程序的性能数据,进行性能提升.Instruments提供了很多类型的Template,用于特定场景的分析.这里选了3种常 ...