gpt4 book ai didi

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

转载 作者:我是一只小鸟 更新时间:2023-08-05 22:34:11 27 4
gpt4 key购买 nike

  • 背景

今天有同事问我一道关于数据库SQL的面试题,我刚开始随便给了一个思路,后来思索发现这个思路有漏洞,于是总结下来,仅供参考.

问题: 薪水表中是员工薪水的基本信息,包括雇员编号,和薪水,查询除去最高、最低薪水后的平均薪水.

  • 1、薪水表信息
                          
                            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
                          
                          );
                        
  • 2、查询分析

思路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-去除最大值与最小值求均值的问题的文章就讲到这里了,如果你想了解更多关于SQL-去除最大值与最小值求均值的问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com