Consulta MYSQL para encontrar todos los empleados con el n-ésimo salario más alto

Las dos tablas son employee_employee y employee

employee_salary

salary_id emp_id salary 

Empleado

 emp_id | first_name | last_name | gender | email | mobile | dept_id | is_active 

Consulta para get todos los empleados que tienen el n-ésimo salario más elevado, donde n = 1,2,3, … cualquier número integer

 SELECT a.salary, b.first_name FROM employee_salary a JOIN employee b ON a.emp_id = b.emp_id WHERE a.salary = ( SELECT salary FROM employee_salary GROUP BY salary DESC LIMIT 1 OFFSET N-1 ) 

Mis preguntas:

1) ¿Hay alguna manera mejor y optimizada de que podamos consultar esto?


2) Está usando LIMIT una buena opción


3) Tenemos más opciones para calcular el n-ésimo salario más alto, ¿cuál es el mejor y qué seguir y cuándo?

Una opción usando:

 SELECT * FROM employee_salary t1 WHERE ( N ) = ( SELECT COUNT( t2.salary ) FROM employee_salary t2 WHERE t2.salary >= t1.salary ) 

Usando el Método de Rango

 SELECT salary FROM ( SELECT @rn := @rn + 1 rn, a.salary FROM tableName a, (SELECT @rn := 0) b GROUP BY salary DESC ) sub WHERE sub.rn = N 

Esto es demasiado largo para un comentario.

Usted ha preguntado lo que parece una pregunta razonable. Hay diferentes maneras de hacer las cosas en SQL y, a veces, algunos methods son mejores que otros. El problema de sorting es solo uno de muchos, muchos ejemplos. La "respuesta" a su pregunta es que, en general, order by va a funcionar mejor que group by en MySQL. Aunque incluso eso depende de los datos particulares y de lo que considera que es "mejor".

Los problemas específicos con la pregunta son que tiene tres consultas diferentes que devuelven tres cosas diferentes.

El primero devuelve todos los empleados con un "range denso" que es el mismo. Esa terminología se usa deliberadamente porque corresponde a la function ANSI dense_rank() que MySQL no admite. Entonces, si sus salarios son 100, 100 y 10, devolverá dos filas con una sorting de 1 y una con una sorting de 2.

El segundo devuelve resultados diferentes si hay vínculos. Si los salarios son 100, 100, 10, esta versión no devolverá filas con una sorting de 1, dos filas con una sorting de 2 y una fila con una sorting de 3.

El tercero arroja un set de resultados completamente diferente, que es solo los salarios y la sorting de los salarios.

Mi comentario fue dirigido a intentar las consultas sobre sus datos. De hecho, debes decidir lo que realmente deseas, tanto desde una perspectiva funcional como desde una perspectiva de performance.

LIMIT requiere que el SQL revise todos los loggings entre 0 y N y, por lo tanto, requiere un time cada vez más atrás en el ranking que desea search. Sin embargo, IMO ese problema no se puede resolver mejor.

  • Como Gordon Linoff sugirió: ejecute su opción en function de su set de datos, utilizando los ranges comúnmente utilizados (¿qué ranges se consultan a menudo, cuáles no? El resultado puede ser rápido en el range 1 pero terrible en el range 100).

  • Ejecute y analice el Plan de ejecución de consultas y cree índices en consecuencia (por ejemplo, en la columna de salarios) y vuelva a evaluar sus consultas.

Otras opciones:

Opción 4:

Puede build una tabla de sorting que sirva como caching. El plan de ejecución de su Limit-Query muestra ( vea sqlfiddle aquí ), que mysql ya crea una tabla temporal para resolver la consulta.

Pros: Fácil y rápido Contras: Te obliga a regenerar la tabla de sorting cada vez que los datos cambian

Opción 5:

Podría reconsiderar cómo define "ranges". Si tenemos los siguientes salarios:

  1. 100'000
  2. 100'000
  3. 80'000

¿El empleado Nr 3 se considera de range 3 o 2? ¿Están 1 y 2 en el mismo range (range 1), pero 3 está en el range 3?

Si define range = order, puede simplificar enormemente la consulta a

SELECCIONE a.salary, b.first_name FROM employee_salary a, employee b DONDE a.emp_id = b.emp_id ordere por salario desc LIMIT 1 OFFSET 4

demo: http://sqlfiddle.com/#!2/e7321d/1/0

testing esto,

 SELECT * FROM one as A WHERE ( n ) = ( SELECT COUNT(DISTINCT(b.salary)) FROM one as B WHERE B.salary >= A.salary ) 

Supongamos que la tabla emp_salary tiene los siguientes loggings:

Tabla de sueldos del empleado

Y desea seleccionar a todos los empleados con n-ésimo (N = 1,2,3, etc.) el más alto / el más bajo (solo cambio> (para el más alto), <(para el operador más bajo según sus necesidades), utilice el siguiente sql:

 SELECT DISTINCT(a.salary), a.id, a.name FROM emp_salary a WHERE N = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b WHERE b.salary >= a.salary ); 

Por ejemplo, si desea seleccionar a todos los empleados con el segundo salario más alto, use debajo de sql:

  SELECT DISTINCT(a.salary), a.id, a.name FROM emp_salary a WHERE 2 = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b WHERE b.salary >= a.salary ); 

Segunda lista de salarios más alta

Pero si desea mostrar solo el segundo salario más alto (solo logging único), use el siguiente sql:

 SELECT DISTINCT(a.salary), a.id, a.name FROM emp_salary a WHERE 2 = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b WHERE b.salary >= a.salary ) limit 1; 

Segundo salario más alto (solo registro, no duplicado)