Pregunta de la entrevista HiveSql 12-Cómo analizar el salario promedio sin los valores máximo y mínimo (byte beating)

Tabla de contenido

0 Descripción del problema

1 preparación de datos

2 Análisis de datos

3 resumen


0 Descripción del problema

  • La tabla de salarios es la información básica del salario del empleado, incluido el número de empleado, el número de departamento y el salario.
  • La primera línea indica que el empleado cuyo número de empleado es 10001 está en el departamento 1 y el salario es 60117 yuanes;
  • La segunda línea indica que el empleado cuyo número de empleado es 10002 está en el departamento 2 y el salario es de 92,102 yuanes;
  • ...
  • La línea 10 indica que el empleado cuyo número de empleado es 10010 está en el departamento 1 y el salario es 76884 yuanes

Pregunta: Consultar el salario promedio de cada departamento después de quitar el salario más alto y más bajo, y mantener el número entero. 

1 preparación de datos

(1) Datos

datos básicos
Número de empleado Número de departamento salario
10001 1 60117
10002 2 92102
10003 2 86074
10004 1 66596
10005 1 66961
10006 2 81046
10007 2 94333
10008 1 75286
10009 2 85994
10010 1 76884

 

(2) Crear tabla SQL

drop table if exists dan_test.salary

CREATE TABLE dan_test.salary (

emp_num string ,

dep_num string ,

salary string

)

ROW format delimited FIELDS TERMINATED BY ",";

(3) Cargar datos

load data local inpath "/home/centos/dan_test/salary.txt" into table salary;

 (4) Consultar datos

 

2 Análisis de datos

Objetivo: es necesario consultar el salario promedio de cada departamento después de eliminar el salario más alto y más bajo, y mantener el número entero. 

Tres puntos clave de información:

  •   (1) Cada departamento (agrupado por departamento)
  • (2) Excluya el salario más alto y más bajo. (Necesita encontrar primero el salario más alto y más bajo, y filtrar, la clave para esta pregunta)
  • (3) Calcule el promedio sobre la base de (1) y (2), y mantenga el número entero

 Idea 1: Encuentre y filtre el salario más alto y más bajo en el departamento. Utilice la función de ventana row_number () para marcar los datos agrupados por departamento y ordenados por salario

El SQL es el siguiente:

select emp_num
      ,dep_num
	  ,salary
	  ,row_number() over(partition by dep_num order by salary) as rn1 --标记最小
	  ,row_number() over(partition by dep_num order by salary desc) rn2 --标记最大
from salary

Los resultados de la consulta son los siguientes:

Según los requisitos, se filtran los resultados intermedios, es decir, se establecen las condiciones de rn1> 1 y rn2> 1. Cuando hay varios conjuntos de resultados de ventana y el campo mostrado participa en la operación de ventana, el campo está sujeto a la última función de ventana. Por ejemplo, el resultado de visualización de salario de esta pregunta se muestra en función del resultado de la última ventana. El SQL final es el siguiente

select *
from(
select emp_num
      ,dep_num
	  ,salary
	  ,row_number() over(partition by dep_num order by salary) as rn1 --标记最小
	  ,row_number() over(partition by dep_num order by salary desc) rn2 --标记最大
from salary
) t
where rn1 > 1 and rn2 > 1

Idea 2: para filtrar lo más grande y lo más pequeño, podemos ordenar solo una vez, primero encontrar el número total de filas de agrupación y luego ordenar el salario en orden ascendente, luego el resultado que necesitamos es 1 <rn <cn. El SQL específico es el siguiente:

select emp_num
      ,dep_num
	  ,salary
	  ,count(1) over(partition by dep_num) as cn --求出总行数
	  ,row_number() over(partition by dep_num order by salary ) rn --按照薪水升序排序
from salary

 

Los resultados finales filtrados son los siguientes:

select *
from(
select emp_num
      ,dep_num
	  ,salary
	  ,count(1) over(partition by dep_num) as cn --求出总行数
	  ,row_number() over(partition by dep_num order by salary ) rn --按照薪水升序排序
from salary
) t
where rn > 1 and rn < cn

 El SQL para encontrar el promedio final es el siguiente:

---方法1
select t.dep_num,round(avg(t.salary),0) as avg_salary
from
  (
  select *,
  row_number() over (partition by dep_num order by salary desc) as rn1,
  row_number() over (partition by dep_num order by salary) as rn2
  from salary
  ) t
where t.rn1 > 1 and t.rn2 > 1
group by t.dep_num;

--------方法2
select t.dep_num,round(avg(t.salary),0) as avg_salary
from
  (
  select emp_num
        ,dep_num
	    ,salary
	    ,count(1) over(partition by dep_num) as cn --求出总行数
	    ,row_number() over(partition by dep_num order by salary ) rn --按照薪水升序排序
  from salary
  ) t
where t.rn > 1 and t.rn < t.cn
group by t.dep_num;

Los resultados del cálculo son los siguientes:

Método 3: método de fórmula . Según la idea normal de promediar: (suma (salario) -max (salario) -min (salario)) / recuento (salario) -2 - agrupados por departamento.

(1) Primero encuentre el valor de salario máximo, el valor de salario mínimo y el número total de valores de salario para cada departamento. El SQL específico es el siguiente:

select 
       dep_num
	  ,count(salary) as cn --求出总个数
	  ,max(salary) as max_salary --salary最大值
	  ,min(salary) as min_salary --salary最小值
	  ,sum(salary) as sum_salary --salary总和
from salary
group by dep_num

 El resultado de la solicitud es el siguiente:

(2) Encuentre el valor promedio de cada departamento después de eliminar los valores máximo y mínimo (método de fórmula).

En este momento, luego de agrupar por departamento, dado que la adquisición de campos que no están en la agrupación debe ser colocada en la función agregada a ser utilizada, usamos la función max () para obtener los campos restantes, pero ¿afectará el resultado? De hecho, no afectará, porque el valor de retorno del resultado del paso anterior es después de la agregación, cada departamento tiene solo un dato y cada campo tiene solo un valor, así que si usa max (), min ( ), sum () Y otras funciones tienen el mismo resultado. Esto también es una técnica.Cuando solo hay un valor en este grupo después de agrupar, para extraer el valor del campo, podemos usar la función max (), min () para extraer, y la función agregada a menudo también tiene la función de filtrado de valores NULL. Con esta función, a menudo proporciona mucha comodidad para las consultas de nivel superior al escribir SQL.

El SQL final es el siguiente:

select dep_num
    ,(max(sum_salary) - max(max_salary) -max(min_salary)) / (max(cn) -2) as avg_salary--使用max()函数提取非group by组中的字段值,供上层计算
from (
select 
       dep_num
	  ,count(salary) as cn --求出总个数
	  ,max(salary) as max_salary --salary最大值
	  ,min(salary) as min_salary --salary最小值
	  ,sum(salary) as sum_salary --salary总和
from salary
group by dep_num
) t
group by dep_num

El resultado final es el siguiente:

3 resumen

Un resumen de los puntos de conocimiento utilizados en este artículo:

  • (1) El rol y las habilidades de uso de la función de clasificación. numero de fila()
  • (2) El uso de la función round ().
  • (3) Cómo excluir las habilidades máximas y mínimas
  • (4) Cómo obtener el valor en el campo no agrupar por

Supongo que te gusta

Origin blog.csdn.net/godlovedaniel/article/details/112372060
Recomendado
Clasificación