在Oracle Subquery中获取订单后的第一行

时间:2010-08-03 06:30:36

标签: sql database oracle oracle10g limit

我有一个表学生(身份证,姓名,部门,年龄,分数)。我想找到每个系最高(最年轻的学生)得分最年轻的学生。在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关键字。我必须自己加入学生表两次才能查询结果。在oracle中,我使用以下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

有没有人有任何想法为oracle简化上述SQL。

4 个答案:

答案 0 :(得分:26)

尝试这个

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;

答案 1 :(得分:11)

除了艾伦的回答,这也很好用:

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

答案 2 :(得分:6)

除了Bharat的回答之外,还可以在Oracle的子查询中使用ORDER BY来实现这一点(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);

如果您使用此方法,您可能想要删除子查询,只需使用rownum = 1。这将导致不正确的结果,因为排序将在标准之后应用(您将获得排序的1行,而不是排序集中的一行)。

答案 3 :(得分: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'