首页 > 数据库 >SQL-去除最大值与最小值求均值的问题

SQL-去除最大值与最小值求均值的问题

时间:2023-08-05 15:01:19浏览次数:35  
标签:salary INSERT no 最大值 salaries 最小值 VALUES emp 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都只是去除一个最高薪水和一个最低薪水,然后求平均值。所以才导致计算出的结果不一致。

 

标签:salary,INSERT,no,最大值,salaries,最小值,VALUES,emp,SQL
From: https://www.cnblogs.com/yeyuzhuanjia/p/17607965.html

相关文章

  • Docker-Compose 一键部署mysql及初始化sql脚本
    1.部署前提:服务器具备docker和docker-compose环境2.镜像准备:-mysql:DockerFile文件:FROMmysql:5.7.41COPY*.sql/docker-entrypoint-initdb.d/初始化sql脚本xxx.sql放在DockerFile文件同级目录下执行指令:dockerbuild-fdockerfile_mysql-tmysql:1.0.0.......
  • Sqlmap的使用
    1、get型提交sqlmap.py-u+网址sqlmap.py-uhttp://127.0.0.1/sqli/Less-1/?id=1参数levellevel的等级越高,测试的等级越广,>=2时会检查cookie里的参数>=3时检查user-agent和refereer--dbs              查询所有的数据库sqlmap.py-uhttp://127.0.0.1/sql......
  • 老派Sql之必要,逆天,我在ef core中使用ado.net!
    Wlkr.Core.EFCore逆天,我在efcore中使用ado.net!老派Sql之必要当你开发生涯中基本只用一两种数据库当你觉得用EF的类写报表时很别扭当你觉自己的Sql(Server)语句写得出神入化当你觉自己的Sql(Server)语句比EF生成的更优化当你刚从.netframework转.netcore,还不知道sqls......
  • MySql之锁
    MySql之锁一、全局锁对整个数据库加锁应用:数据库所有表备份二、表级锁1.表锁分为两类:表共享读锁readlock表独占写锁writelock2.元数据锁避免DML语句和DDL语句的冲突问题3.意向锁:作用:针对行锁和表锁,当表中有行锁时,会同时加一把意向锁,表锁不用去逐行遍历是否加了行锁,......
  • 最简单的Qt连接MYSQL的方法
    最简单的Qt连接MYSQL的方法⭐当我试图在项目中连接本地的mysql时,反复出现:QMYSQLdrivernotloaded,显示没有成功加载mysql的驱动,在网上查询了很多教程和视频,大多为互相转载且老旧,耗费了大半天还是没有构建成功,通常的解决方法是在本地构建mysql驱动(通过安装qt时勾选的src选项里......
  • MySQL之InnoDB存储结构 转载 https://juejin.cn/post/7253816086679846972
    1InnoDB存储引擎InnoDB存储引擎最早由InnobaseOy公司开发(属第三方存储引擎)。从MySQL5.5版本开始作为表的默认存储引擎。该存储引擎是第一个完整支持ACID事务的MySQL存储引擎,特点是行锁设计、支持MVCC、支持外键、提供一致性非锁定读,非常适合OLTP场景的应用使用。目前也是应用......
  • MySQL查询排序和分页
    连接数据库mysql-hlocalhost-uroot-proot排序查询语法:select字段列表from表名orderby字段1排序方式1,字段3排序方式2,字段3排序方式3,....;ASC:升序(默认值)DESC降序注意:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序。根据年龄对公司......
  • Sql Server 存储过程
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Access文件导入数据--------------------------......
  • MySQL内存使用排查
    MySQL使用内存上升90%!在运维过程中50%的几率,会碰到这样的问题。算是比较普遍的现象。MySQL内存使用率过高,有诸多原因。普遍原因是使用不当,还有MySQL本身缺陷导致的。到底是哪方面的问题,那就需要一个一个进行排查。下面介绍排查思路:1.参数配置需要确认,内存是否设置合理MySQL内......
  • mysql 命令安装
    1.  mysql 下载安装好压缩文件,下面我们进入正题,少废话。09:39:112023-08-05先到mysql官方网站下载:https://dev.mysql.com/downloads/mysql/ 解压后为这样 执行这个代码mysqld--initialize--console后面出现密码自己保存一下  然后继续安装m......