2012-10-31 3 views
8

私はIDごとに最高以降でのみ行を選択しようとしているサブクエリを使用せずに最大シーケンスでローのみを選択するにはどうすればよいですか?

ID | Seq | Age 
------------------- 
A  1  20 
A  2  30 
B  1  25 
B  2  32 
B  3  44 
B  4  48 
C  1  11 

これは

SELECT ID, Age 
FROM Persons a 
WHERE Seq = (SELECT MAX(Seq) FROM Persons b WHERE a.ID = b.ID) 

を動作しているように見えます。しかし、これは最善の方法、唯一の方法ですか?私はサブクエリを使用するのが好きではありませんし、何かを使うことができると思いますが、それは何かを忘れてしまいます。何か案が?

+0

どのようなrdbmsを使用していますか? –

+0

主にSQL Serverですが、オラクルと互換性があればそれは最高です – jenswirf

+0

私の 'ROW_NUMBER'アプローチはSQl-FiddleでテストしたようにOracleでも動作します。私の答えの中のリンクを見てください。 –

答えて

5

SQL-Serverの仮定(> = 2005)またはOracle(10グラム):

WITH CTE AS 
( 
    SELECT 
     ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Seq DESC) AS RN 
     , ID, Age 
    FROM 
     Persons 
) 
SELECT ID, Age 
FROM CTE 
WHERE RN = 1 

ROW_NUMBERは、結果セットのパーティション内の行の順序番号を返します。

編集は:あなたがここに見ることができるようにオラクルでも動作します:一般的にhttp://sqlfiddle.com/#!4/b7e79/2/0

+0

私の脳をリフレッシュしてくれてありがとう、過去にこれを使っていました。 – superachu

1

を、あなたはウィンドウやランキング機能を使用するためにneeed -

など、
select * 
from 
(
    select *, row_number() over (partition by id order by age desc) rn 
    from yourtable 
) v 
where rn = 1 

Rank()Row_number()この意志SQL Server 2005+で動作します.Oracleではフィールド名を明示的に指定する必要があります。*

+0

これも私が考えていた最良の方法です。しかし、そこには2つの選択句があり、それが気に入らないのであれば、インナーセレクトを取るだけで、アプリではランク1でないものを見たことがあります;) – OzrenTkalcecKrznaric

1

Jus tはあなたがウィンドウ関数をサポートしていない、あなたが使用できるRDBMSを使用する場合には:

SELECT Persons.ID, Persons.Age, Persons.Seq 
FROM Persons 
     INNER JOIN 
     ( SELECT Persons.ID, MAX(Seq) AS Seq 
      FROM Persons 
      GROUP BY Persons.ID 
     ) MaxP 
      ON MaxP.ID = Persons.ID 
      AND MaxP.Seq = Persons.Seq 

それはまだサブクエリを含むが、私は1つせずにこれを行う方法が表示されない、また私が本当になぜあなたがそれらを避けたいのかを理解する。

関連する問題