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函数 ...
随机推荐
- vue中点击其他任意位置关闭弹框
mounted() { //点击任意位置关闭区域弹窗 document.addEventListener('click', (e) => { //获取弹窗对象 const userCon = d ...
- vue移动端适配方案
一.安装postcss-px-to-viewport插件 1.使用npm安装 $ npm install postcss-px-to-viewport --save-dev 2.或者使用yarn安装 ...
- 2021-11-15:四数相加 II。给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= i,
2021-11-15:四数相加 II.给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= ...
- 从前后端的角度分析options预检请求
摘要:options预检请求是干嘛的?options请求一定会在post请求之前发送吗?前端或者后端开发需要手动干预这个预检请求吗?不用文档定义堆砌名词,从前后端角度单独分析,大白话带你了解! 本文分 ...
- 【Java】JTable的数据刷新
前言 这段时间在写一个大实验,水果超市管理系统,yes,我觉得挺大的,但是就当成了一个实验,接下来还有一个课程设计和一个实训,more bigger... 问题 在我把其他的都写好的时候去写UI层,发 ...
- 详解JS的Object.assign()
Object.assign() 通过复制一个或多个对象来创建一个新的对象. 语法 Object.assign(target, ...sources) 描述 如果目标对象中的属性具有相同的键,则属性将被 ...
- celery笔记二之建立celery项目、配置及几种加载方式
本文首发于公众号:Hunter后端 原文链接:celery笔记二之建立celery项目.配置及几种加载方式 接下来我们创建一个 celery 项目,文件夹及目录如下: proj/__init__.py ...
- 适用于Linux命令的10个R函数
由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. 这篇文章将介绍 10 个不同的 Linux 命令及其 R 实现方法. 如果您有兴趣学习更多 R ...
- 第三届陕西省大学生网络安全技能部分WP
web easyrce 题目代码如下: <?php error_reporting(0); highlight_file(__FILE__); if (!empty($_GET['PK'])){ ...
- 自然语言处理 Paddle NLP - 基于预训练模型完成实体关系抽取
自然语言处理 Paddle NLP - 信息抽取技术及应用 重点:SOP 图.BCEWithLogitsLoss 基于预训练模型完成实体关系抽取 信息抽取旨在从非结构化自然语言文本中提取结构化知识,如 ...