• 背景

今天有同事问我一道关于数据库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-去除最大值与最小值求均值的问题的更多相关文章

  1. Java初学者作业——编写 Java 程序,用户输入 3 个操作数,分别求出最大值、最小值和平均值。

    返回本章节 返回作业目录 需求说明: 编写 Java 程序,用户输入 3 个操作数,分别求出最大值.最小值和平均值. 实现思路: 定义 Java 类,定义 3 个方法,用来求 3 个数字的最大值.最小 ...

  2. Java开发中经典的小实例-(比较输入数值的最大值、最小值和平均值)

    //输入数字个数来产生数字并且比较大小 import java.util.Scanner;public class Test1 {     public static void main(String ...

  3. Java对二叉搜索树进行插入、查找、遍历、最大值和最小值的操作

    1.首先,须要一个节点对象的类.这些对象包括数据.数据代表存储的内容,并且还有指向节点的两个子节点的引用 class Node { public int iData; public double dD ...

  4. 不需要sql进行计算数据的平均值、最大值、最小值、和

    介绍下SqlServer.前端js.后台C#三个阶段对均值.最大值.最小值.和计算int[] jisuan = {0, 1, 3, 5, 7,8 }; List<int> jisuan2 ...

  5. POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 53703   Accepted: 25237 ...

  6. JS创建一个数组1.求和 2.求平均值 3.最大值 4.最小值 5.数组逆序 6.数组去重 0.退出

    rs = require("readline-sync"); let arr = []; console.log("请输入数组的长度:"); let arr_l ...

  7. Jsの数组练习-求一组数中的最大值和最小值,以及所在位置

    要求:求一组数中的最大值和最小值,以及所在位置 代码实现: <!DOCTYPE html> <html lang="en"> <head> &l ...

  8. C语言:用指针求最大值和最小值

    用指针求数组最大值和最小值(10分) 题目内容: 用指针求含有十个元素的数组最大值和最小值 主函数参考 int main() { int a[10],i,maxnum,minnum; for(i=0; ...

  9. Java求一个数组中的最大值和最小值

    原创作品,转载请注明出处:https://www.cnblogs.com/sunshine5683/p/9927186.html 今天在工作中遇到对一个已知的一维数组取出其最大值和最小值,分别用于参与 ...

  10. java从键盘输入若干数,求其最大值,最小值,平均值。等等

    总结:有一定基础的人,应该发现第一个程序可以运行,其实它有个致命的错误.有谁能一眼看出来呢?第二个程序是对的. 这个题目求最大值,最小值,平均值我不会求,不知道这个if判断放在类的外面还是main函数 ...

随机推荐

  1. 音视频八股文(10)-- mp4结构

    介绍 mp4⽂件格式⼜被称为MPEG-4 Part 14,出⾃MPEG-4标准第14部分 .它是⼀种多媒体格式容器,⼴泛⽤于包装视频和⾳频数据流.海报.字幕和元数据等.(顺便⼀提,⽬前流⾏的视频编码格 ...

  2. 2021-03-24:给定一个整数组成的无序数组arr,值可能正、可能负、可能0。给定一个整数值K,找到arr的所有子数组里,哪个子数组的累加和等于K,并且是长度最大的。返回其长度。

    2021-03-24:给定一个整数组成的无序数组arr,值可能正.可能负.可能0.给定一个整数值K,找到arr的所有子数组里,哪个子数组的累加和等于K,并且是长度最大的.返回其长度. 福大大 答案20 ...

  3. Django4全栈进阶之路20 项目实战(三种方式开发部门管理):方式一:FBV

    1.模型 from django.db import models from django.contrib.auth.models import User # Create your models h ...

  4. Visual Studio2019打开电脑摄像头

    #include<iostream> //opencv头文件 #include<opencv2/opencv.hpp> using namespace std; using n ...

  5. 每周更新 | Verilog测试用例及波形展示图功能上线

    Hi,亲爱的技术伙伴,经过产研团队的努力,本周ShowMeBug有以下4个功能上线啦- 芯片语言 Verilog 支持测试用例 芯片语言 Verilog 支持测试用例,自动评分同步上线- 同时,Ver ...

  6. List的拆分的几种方式

    开发中我们可能会遇到一个大的集合,然后我们需要对集合进行拆分,然后再对拆分的集合进行相关的操作.当然我们可以自己写一个拆分的方法,我自己写过用了不少代码,但是感觉还不是很好,最近看了不少工具才发现很多 ...

  7. 基于Jmeter+ant+Jenkins+钉钉机器人群通知的接口自动化测试

    前言 搭建jmeter+ant+jenkins环境有些前提条件,那就是要先配置好java环境,本地java环境至少是JDK8及以上版本,最好是JAVA11或者JAVA17等较高的java环境,像jen ...

  8. Python 安装教程,新手入门(超详细)含Pycharm开发环境安装教程

    目录 一.Python介绍 二.Python安装教程 (一)Python的下载 (二)Python的安装 三.Pycharm开发工具的安装 (一)Pycharm介绍 (二)Pycharm的下载 (三) ...

  9. 大家都说Java有三种创建线程的方式!并发编程中的惊天骗局!

    在Java中,创建线程是一项非常重要的任务.线程是一种轻量级的子进程,可以并行执行,使得程序的执行效率得到提高.Java提供了多种方式来创建线程,但许多人都认为Java有三种创建线程的方式,它们分别是 ...

  10. Tab切换以及倒计时组件封装

    1.Tab组件 功能 支持默认选中tab 子元素可以是文本或者图片 自定义tab的数量,并自适应展示 实现方式 用ul > li标签遍历传入的tabs数组参数渲染 判断是否传入背景,未传则显示文 ...