• 背景

今天有同事问我一道关于数据库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. 【Linux】文本处理及Shell编程

    1.统计出/etc/passwd文件中其默认shell为非/sbin/nologin的用户个数,并将用户都显示出来 [root@CentOS8 ~]# cat /etc/passwd root:x:0 ...

  2. CentOS 7 部署SonarQube 8.3版本及配置jenkins分析C#代码

    安装SonarQube 8.3版本 官方文档 下载地址 准备工作 准备一台CentOS 7服务器 SonarQube 8.3版本只支持Java 11 (下载Java 11) 安装PostgreSQL ...

  3. 【C#】图片上传并根据长宽大小进行正方形、长方形及等比缩放。

    #region 正方型裁剪并缩放 /// <summary> /// 正方型裁剪 /// 以图片中心为轴心,截取正方型,然后等比缩放 /// 用于头像处理 /// </summary ...

  4. [Flink] Flink Job运行状态正常,但日志中偶报“FlinkException: The file LOG does not exist on the TaskExecutor.”

    0 序言 Flink : 1.12 job start running time : 2022-12-27 17:40:47 problem throw time : 2023-05-11 16:41 ...

  5. 2021-04-19:手写代码:最小生成树算法之Kruskal。

    2021-04-19:手写代码:最小生成树算法之Kruskal. 福大大 答案2021-04-19: 并查集.边从小到大,找最小边,无环. 代码用golang编写.代码如下: package main ...

  6. Dapr在Java中的实践 之 服务调用

    服务调用 通过服务调用(Service-to-service Invocation),服务可以使用 gRPC 或 HTTP 这样的标准协议来发现并可靠地与其他服务通信. Dapr采用边车(Sideca ...

  7. 【HarmonyOS】详解低代码端云一体化开发之数据模型

    [关键字] 元服务.低代码平台.端云一体化开发.数据模型.拖拽式UI [1.写在前面] 上一篇中分享了关于低代码平台开发元服务的基本使用,有兴趣的可以看一下,文章地址如下: https://devel ...

  8. CoFiltering:BestPracticesandTechniquesinTextGeneration

    目录 Co-Filtering: Best Practices and Techniques in Text Generation Introduction: Text generation has ...

  9. [python] 基于matplotlib-scalebar库绘制比例尺

    matplotlib-scalebar是一个Python库,用于在matplotlib图形中添加比例尺.它允许用户指定比例尺的大小.位置.字体和颜色,以及比例尺的单位.该库支持不同的比例尺单位,例如米 ...

  10. python3使用PIL添加中文文本水印背景

    环境:Windows10_x64  Python版本 :3.9.2 Pillow版本:9.1.1   写的博客文章被转载且不注明出处的情况时有发生,甚至有部分转载者将文章配图添加自己的水印!为了保护作 ...