web-dev-qa-db-ja.com

OracleSubqueryでorderbyの後に一番上の行を取得します

私にはテーブルの学生がいます(ID、名前、部門、年齢、スコア)。各学科の中で(最年少の学生の中で)スコアが最も高い最年少の学生を見つけたいと思います。 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/toplikeキーワードはありません。結果をクエリするには、studentテーブルをそれ自体と2回結合する必要があります。 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

上記のSQLforOracleを単純化するアイデアはありますか。

8
James

これを試してみてください

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;
26
Bharat

アランの答えに加えて、これもうまく機能します:

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

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行ではなく、並べ替えられた1行が取得されます)。

6
Allan
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'
1
Diwakar Kumar