Pergunta

Sou novo em trabalhar com funções 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

Quero o departamento e o funcionário com salário mínimo.

Os resultados devem parecer:

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

EDIT: Aqui está o SQL que eu tenho (mas é claro, ele também não funciona, pois deseja a equipe do grupo por cláusula):

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

Solução

Eu acho que a função de classificação () não é o caminho a seguir com isso, por duas razões.

Em primeiro lugar, provavelmente é menos eficiente que um método baseado em min ().

A razão para isso é que a consulta deve manter uma lista ordenada de todos os salários por departamento, pois verifica os dados, e a classificação será atribuída posteriormente relendo esta lista. Obviamente, na ausência de índices que podem ser aproveitados para isso, você não pode atribuir uma classificação até que o último item de dados seja lido e a manutenção da lista seja cara.

Portanto, o desempenho da função de classificação () depende do número total de elementos a serem digitalizados e, se o número for suficiente para que a classificação derrame para o disco, o desempenho entrará em colapso.

Isso provavelmente é mais eficiente:

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

Esse método requer apenas que a consulta mantenha um único valor por departamento do valor mínimo encontrado até agora. Se um novo mínimo for encontrado, o valor existente será modificado, caso contrário, o novo valor será descartado. O número total de elementos que precisam ser mantidos na memória está relacionado ao número de departamentos, não ao número de linhas digitalizadas.

Pode ser que o Oracle tenha um caminho de código para reconhecer que a classificação não precisa ser calculada neste caso, mas eu não apostaria nela.

A segunda razão para não gostar de classificação () é que ela apenas responde à pergunta errada. A questão não é "quais registros têm o salário que é o primeiro ranking quando os salários por departamento estão ascendentes ordenados", é "quais registros têm o salário que é o mínimo por departamento". Isso faz uma grande diferença para mim, pelo menos.

Outras dicas

Eu acho que você estava bem próximo da sua consulta original. O seguinte seria executado e corresponderia ao seu caso de teste:

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

Em contraste com as soluções de classificação (), este garante no máximo uma linha por departamento. Mas isso sugere um problema: o que acontece em um departamento onde há dois funcionários com o menor salário? As soluções de classificação () devolverão os dois funcionários - mais de uma linha para o departamento. Esta resposta escolherá um arbitrariamente e garantirá que haja apenas uma para o departamento.

Você pode usar o RANK() sintaxe. Por exemplo, esta consulta dirá onde um funcionário está dentro do departamento em relação ao tamanho do seu salário:

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

Você poderia então consultar isso onde 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top