Creo que la función Rank() no es el camino a seguir con esto, por dos razones.
En primer lugar, es probablemente menos eficiente que un método basado en Min().
La razón de esto es que la consulta debe mantener una lista ordenada de todos los salarios por departamento a medida que escanea los datos, y luego se asignará el rango más adelante al volver a leer esta lista. Obviamente, en ausencia de índices que puedan aprovecharse para esto, no puede asignar un rango hasta que se haya leído el último elemento de datos, y el mantenimiento de la lista es costoso.
Por lo tanto, el rendimiento de la función Rank() depende del número total de elementos que se analizarán, y si el número es suficiente para que el ordenamiento se derrame en el disco, el rendimiento colapsará.
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 se encuentra un nuevo mínimo, se modifica el valor existente, de lo contrario, se descarta el nuevo valor. La cantidad total de elementos que deben mantenerse en la memoria se relaciona con la cantidad de departamentos, no con el número de filas escaneadas.
Podría ser que Oracle tenga una ruta de código para reconocer que en este caso realmente no es necesario calcular el rango, pero yo no apostaría.
La segunda razón para desagradar el rango() es que simplemente responde la pregunta incorrecta. La pregunta no es "¿Qué registros tienen el salario que es la primera clasificación cuando los salarios por departamento están ordenados ascendentemente?", Es "Qué registros tienen el salario que es el mínimo por departamento". Eso hace una gran diferencia para mí, al menos.
Gracias David. Después de considerar sus beneficios, reformulé su solución. –