Получить верхнюю строку после заказа в Oracle Subquery - PullRequest
8 голосов
/ 03 августа 2010

У меня есть ученик за столом (имя, фамилия, отдел, возраст, оценка). Я хочу найти самого молодого студента, который имеет самый высокий (среди самых молодых студентов) балл на каждом факультете. В SQL Server я могу использовать следующий SQL.

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).

Однако в Oracle вы не можете использовать предложение order by в подзапросе, и здесь нет ключевого слова limit / top like. Я должен соединить таблицу учеников с собой два раза, чтобы запросить результат. В оракуле я использую следующий 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

Кто-нибудь задумывается упростить приведенный выше SQL для оракула?

Ответы [ 4 ]

26 голосов
/ 03 августа 2010

попробуйте это

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;
11 голосов
/ 21 мая 2014

В дополнение к ответу Аллана, это тоже отлично работает:

select * 
from (SELECT * 
  FROM student
  order by age asc, 
           score desc) 
where rownum = 1;
6 голосов
/ 03 августа 2010

В дополнение к ответу Бхарата это можно сделать с помощью ORDER BY в подзапросе в Oracle (как указал Джеффри Кемп):

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);

Если вы используете этот метод, выможет возникнуть искушение удалить подзапрос и просто использовать rownum = 1.Это приведет к неверному результату, так как сортировка будет применена после критериев (вы получите 1 отсортированную строку, а не одну строку из отсортированного набора).

1 голос
/ 12 мая 2011
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'
...