2010-08-03 15 views
8

Tengo una tabla de estudiantes (identificación, nombre, departamento, edad, puntaje). Quiero encontrar al estudiante más joven que tenga el puntaje más alto (de los estudiantes más jóvenes) de cada departamento. En SQL Server, puedo usar el siguiente SQL.Obtenga la fila superior después de la orden en Oracle Subquery

select * from student s1 
where s1.id in 
(select s2.id from student s2 
where s2.department = s1.department order by age asc, score desc top 1). 

Sin embargo, en Oracle, no se puede utilizar la cláusula ORDER BY en la sub consulta y no hay límite/superior como palabra clave. Tengo que unirme a la mesa de estudiantes consigo mismo dos veces para consultar el resultado. En Oracle, utilizo el siguiente SQL.

select s1.* from student s1, 
(select s2.department, s2.age, max(s2.score) as max_score from student s2, 
(select s3.department, min(s3.age) as min_age from student s3 group by s3.department) tmp1 where 
s2.department = tmp1.department and s2.age = tmp1.min_age group by s2.department, s2.age) tmp2 
where s1.department =tmp2.department and s1.age = tmp2.age and s1.score=tmp2.max_score 

¿Alguien tiene alguna idea de simplificar el SQL anterior para Oracle?

+1

En Oracle, * puede * utilizar la cláusula ORDER BY en una subconsulta. –

+0

Hay una solución mucho más simple, sin funciones analíticas, vea la respuesta aceptada a mi pregunta: http://stackoverflow.com/questions/38180445/oracle-left-join-very-big-table-and-limit-the-joined -rows-to-one-with-the-large – Dany

Respuesta

24

prueba este

select * from 
    (SELECT id, name, department, age, score, 
    ROW_NUMBER() OVER (partition by department order by age desc, score asc) srlno 
    FROM student) 
where srlno = 1; 
+0

Tuve un escenario similar, pensado para manejar usando el bloque pl/sql, ¡pero tu solución funcionó perfectamente! – Rakesh

5

Además de la respuesta de Bharat, es posible hacer esto utilizando ORDER BY en la sub-consulta en Oracle (como señalar por Jeffrey Kemp):

SELECT * 
FROM student s1 
WHERE s1.id IN (SELECT id 
       FROM (SELECT id, ROWNUM AS rn 
         FROM  student s2 
         WHERE s1.department = s2.department 
         ORDER BY age ASC, score DESC) 
       WHERE rn = 1); 

Si usa este método, puede tener la tentación de eliminar la subconsulta y simplemente usar rownum = 1. Esto daría como resultado el resultado incorrecto, ya que la clasificación se aplicaría después de los criterios (obtendría una fila que se ordenó, no una fila del conjunto ordenado).

+0

La pregunta realmente pregunta a la fila superior de "cada departamento". No está utilizando el departamento para agrupar los resultados. Probablemente esta respuesta sea útil para personas que buscan preguntas similares al título sin leer el contenido de la pregunta. Pero quiero señalar la diferencia para las personas que comparan soluciones (porque no obtendrán los mismos resultados). –

+0

@Protron: ¡Buena captura! He actualizado la respuesta. – Allan

1
select to_char(job_trigger_time,'mm-dd-yyyy') ,job_status from 
(select * from kdyer.job_instances ji INNER JOIN kdyer.job_param_values pm 
on((ji.job_id = pm.job_id) and (ji.job_spec_id = '10003') and (pm.param_value='21692')) 
order by ji.job_trigger_time desc) 
where rownum<'2' 
10

Además de la respuesta de Allan, esto funciona muy bien también:

select * 
from (SELECT * 
    FROM student 
    order by age asc, 
      score desc) 
where rownum = 1; 
+0

Esto devuelve solo la fila superior de "todos" los resultados. Eso podría coincidir con el título de la pregunta. Pero la pregunta en realidad pregunta a la fila superior de "cada departamento". Es por eso que es más simple que las respuestas de Bharat. –

+0

Es cierto, Protron, realmente me perdí esa distinción, y respondí una pregunta más simple, que en realidad era lo que estaba buscando cuando busqué en Google y encontré este hilo. Entonces, supongo que todas las respuestas son correctas y útiles, dependiendo de lo que el lector realmente esté buscando. Para mi propósito, la respuesta de Allan fue la más útil, y luego la refiné y volví a publicar. Para su propósito, la respuesta de Bharat es la más útil. ¡Todos ganan! (Aunque, he notado que Allan ha editado su respuesta debido a sus indicaciones, pero dejaré la mía como está, ya que es una respuesta perfecta para muchas personas). – SurfingSanta

Cuestiones relacionadas