2010-08-03 1905 views
8

我有一個表student(id,name,department,age,score)。我想找到每個部門中擁有最高(年齡最小的學生)分數的最年輕學生。在SQL Server中,我可以使用以下SQL。在Oracle子查詢中排序後得到第一行

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中,你不能子句中使用子查詢的順序並沒有像關鍵字沒有限制/頂。我必須自己兩次加入學生表來查詢結果。在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。

+1

在Oracle中,子查詢,你可以* *使用ORDER BY子句。 – 2010-08-03 08:09:09

+0

有一個解決方案更簡單,沒有分析功能,請參閱我的問題的接受答案:http://stackoverflow.com/questions/38180445/oracle-left-join-very-big-table-and-limit-the-joined -row-to-one-the-large – Dany 2016-07-05 05:14:25

回答

24

試試這個

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

我有類似的情況,想要處理使用pl/sql塊,但你的解決方案完美無缺! – Rakesh 2015-10-06 11:36:17

5

除了巴拉特的答案,就可以做到這一點使用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行進行排序,而不是排序集合中的一行)。

+0

這個問題實際上是詢問「每個部門」的最上面一行。您沒有使用該部件對結果進行分組。可能這個答案對於那些沒有閱讀問題內容的人看到標題的類似問題很有用。但我想指出人們比較解決方案的區別(因爲他們不會得到相同的結果)。 – 2016-03-14 13:35:30

+0

@Protron:趕上!我已經更新了答案。 – Allan 2016-03-14 14:29:54

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

除了艾倫的回答,這工作太細:

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

這隻返回「全部」結果的第一行。這可能與問題標題相符。但這個問題實際上是要求「每個部門」的第一行。這就是爲什麼它比巴拉特的答案更簡單。 – 2016-03-14 13:30:12

+0

這是真的,Protron我真的錯過了這個區別,並回答了一個更簡單的問題,這實際上是我在Google搜索時找到的,並且找到了這個線程。所以我想所有的答案都是正確和有用的,這取決於讀者實際上在尋找什麼。出於我的目的,艾倫的答案是最有用的,然後我對它進行了改進並轉貼。爲了您的目的,Bharat的答案是最有用的。大家都贏了! (雖然,我注意到艾倫已經編輯了他的答案,因爲你的提示,但我會離開我的,因爲它是很多人的完美答案)。 – SurfingSanta 2016-03-16 00:40:56