Obtener los mejores resultados para cada grupo (en Oracle)
-
02-07-2019 - |
Pregunta
¿Cómo podría obtener N resultados para varios grupos en una consulta de oráculo.
Por ejemplo, dada la siguiente tabla:
|--------+------------+------------|
| emp_id | name | occupation |
|--------+------------+------------|
| 1 | John Smith | Accountant |
| 2 | Jane Doe | Engineer |
| 3 | Jack Black | Funnyman |
|--------+------------+------------|
Hay muchas más filas con más ocupaciones. Me gustaría conseguir Tres empleados (digamos) de cada ocupación.
¿Hay una manera de hacer esto sin usar una subconsulta?
Solución
Esto produce lo que desea, y no utiliza características SQL específicas del proveedor como TOP N o RANK ().
SELECT MAX(e.name) AS name, MAX(e.occupation) AS occupation
FROM emp e
LEFT OUTER JOIN emp e2
ON (e.occupation = e2.occupation AND e.emp_id <= e2.emp_id)
GROUP BY e.emp_id
HAVING COUNT(*) <= 3
ORDER BY occupation;
En este ejemplo, da a los tres empleados los valores más bajos de emp_id por ocupación. Puede cambiar el atributo usado en la comparación de desigualdad, para que le dé a los mejores empleados por nombre, o lo que sea.
Otros consejos
No tengo una instancia de Oracle a la mano en este momento, así que no he probado esto:
select *
from (select emp_id, name, occupation,
rank() over ( partition by occupation order by emp_id) rank
from employee)
where rank <= 3
Aquí hay un enlace sobre cómo funciona el rango: http://www.psoug.org/reference /rank.html
Agregar RowNum al rango:
select * from
(select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank
from employee)
where rank <= 3
probó esto en SQL Server (y usa subconsultas)
select emp_id, name, occupation
from employees t1
where emp_id IN (select top 3 emp_id from employees t2 where t2.occupation = t1.occupation)
simplemente haga un PEDIDO en la subconsulta para satisfacer sus necesidades
No estoy seguro de que esto sea muy eficiente, pero tal vez sea un punto de partida.
select *
from people p1
join people p2
on p1.occupation = p2.occupation
join people p3
on p1.occupation = p3.occupation
and p2.occupation = p3.occupation
where p1.emp_id != p2.emp_id
and p1.emp_id != p3.emp_id
Esto debería darle filas que contengan 3 empleados distintos, todos en la misma ocupación. Desafortunadamente, te dará TODAS las combinaciones de esas.
¿Alguien puede reducir esto por favor?