Pregunta

Soy nuevo en el trabajo con funciones analíticas.

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  10 JOHN  200000
  10 SCOTT 300000
  20 BOB   100000
  20 BETTY 200000
  30 ALAN  100000
  30 TOM   200000
  30 JEFF  300000

Quiero que el departamento y empleado con el salario mínimo.

Los resultados deben ser:

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  20 BOB   100000
  30 ALAN  100000

EDIT: Aquí está el SQL He (pero por supuesto, no funciona como quiera personal en el grupo por la cláusula también):

SELECT dept, 
  emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary)
FROM mytable
GROUP BY dept
¿Fue útil?

Solución

Creo que la función RANK () no es el camino a seguir con esto, por dos razones.

En primer lugar, es probable que sea menos eficiente que un Min () -. Método basado

La razón de esto es que la consulta tiene que mantener una lista ordenada de todos los salarios por departamento, ya que explora los datos y el rango a continuación, se asigna más tarde por volver a leer esta lista. Obviamente, en ausencia de índices que se puede aprovechar para esto, no se puede asignar un rango hasta que el último dato ha sido leído, y el mantenimiento de la lista es caro.

Así que el desempeño de la función Rango () depende del número total de elementos a escanear, y si el número es suficiente que los derrames de ordenar el disco entonces el rendimiento se colapsarán.

Esto es probablemente más eficiente:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

Este método sólo requiere que la consulta a mantener un solo valor por cada departamento del valor mínimo encontrado hasta ahora. Si un nuevo mínimo se encuentra a continuación, se modifica el valor existente, de lo contrario se descarta el nuevo valor. El número total de elementos que se tienen que mantiene en la memoria está relacionada con el número de departamentos, no el número de filas examinadas.

Podría ser que Oracle tiene una ruta de código de reconocer que el rango no necesita realmente a calcular en este caso, pero yo no apostaría por ello.

La segunda razón para tener aversión Rango () es que simplemente responde a la pregunta equivocada. La pregunta no es "registros que tienen el sueldo que es el primer ranking cuando los salarios por departamento están ascendiendo ordenaron", es "registros que tienen el sueldo que es el mínimo por departamento". Eso hace una gran diferencia para mí, al menos.

Otros consejos

Creo que eran bastante estrecha con su búsqueda original. El siguiente sería correr y hacer coincidir el caso de test:

SELECT dept, 
  MIN(emp) KEEP(DENSE_RANK FIRST ORDER BY salary, ROWID) AS emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary, ROWID) AS salary
FROM mytable
GROUP BY dept

A diferencia de la RANK () soluciones, éste garantiza a lo sumo una fila por cada departamento. Pero que alude a un problema: lo que sucede en un departamento donde hay dos empleados en el salario más bajo? Los RANK () volverán soluciones tanto a los empleados - más de una fila para el departamento. Esta respuesta será elegir uno arbitrariamente y asegúrese de que sólo hay una para el departamento.

Puede utilizar la sintaxis RANK(). Por ejemplo, esta consulta le dirá que un empleado se ubica dentro de su departamento con respecto a qué tan grande es su salario:

SELECT
  dept,
  emp,
  salary,
  (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
FROM EMPLOYEES

A continuación, puede consultar desde aquí donde salary_rank_within_dept = 1:

SELECT * FROM
  (
    SELECT
      dept,
      emp,
      salary,
      (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
    FROM EMPLOYEES
  )
WHERE salary_rank_within_dept = 1
select e2.dept, e2.emp, e2.salary
from employee e2
where e2.salary = (select min(e1.salary) from employee e1)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top