Oracleでトップ1にするにはどうすればよいですか?


251

次の方法を教えてください。

select top 1 Fname from MyTbl

ではOracle 11gの




3
「トップ1」を希望する順序を教えてください。
Andrew Wolfe

1
まず第一に、これを実行するためにDBエンジンに依存することは絶対にありません。そのようなことを知りたい場合は、シーケンサーを入れてください。これを行うと、挿入された順に番号が付けられることが保証されます。
FlyingGuy 2015

1
このトピックに関する非常に有益な資料use-the-index-luke.com/sql/partial-results/top-n-queries
Ilia

回答:


257

最初に選択した行だけが必要な場合は、次のことができます。

select fname from MyTbl where rownum = 1

分析関数を使用して、上位のxを順序付けして取得することもできます。

select max(fname) over (rank() order by some_factor) from MyTbl

54
これは、1つの行だけが必要で、どちらでもかまわない場合に適しています。最新のレコードのように特定の行が必要な場合は、Vashの回答のように、副選択でソートを行う必要があります。Oracleは、ソートの前に行番号を割り当てます。
スコットベイリー

4
@スコットうん。それは正しいです。そして、パトリック、良い点は構文が間違っていると思います。それは本当に維持する必要があります(dense_rank()最後...)
mcpeterson

2
最初の例と2番目の例の違いは、最初の例ではA行(任意の行、順序なし)を選択することです。2番目の例では、(以下の例のように)注文の内部クエリを実行せずに、最初の行の値を取得します。
JulesLt 2010

3
MyTblから選択最大(FNAME)を超える(some_factorによってランク()順):正しくない中での構文
ステファン・ガーバー

1
@jclozano「オラクルの非常によく知られた機能ではありません」-に関しては、私は違いますようにお願いします。「よく知られていない機能」はあいまいであることを意味する傾向があり、したがって使用を避けるべきであることを示唆する可能性があるため、これは重要です。これは曖昧ではなく、その使用は避けてはなりません。
Sepster 2015年

166
SELECT *
  FROM (SELECT * FROM MyTbl ORDER BY Fname )
 WHERE ROWNUM = 1;

8
この回答はTOP行を正しく取得します(ROWNUMで制限する前に結果を並べ替えます)。
JulesLt 2010

この答えは正確な翻訳ではありません-元のクエリにはORDER BYがなく、テーブルのすべての列を返しません。
OMGポニー2010

私は正しい立場に立っています(以下を参照)。時間が切れたら投票を切り替えます。
JulesLt 2010

7
@OMGPoniesええ。しかし、おそらく、ほとんどの人が問題をグーグルで経由してこのページにアクセスする人が実際に望んでいることです
NimChimpsky 2015年

4
これは確かにこのスレッドでの勝利の答えでなければなりません。私はtop Xそれを次のように変更できるというメモを追加するかもしれませんWHERE ROWNUM <= X
SomethingSomething

31

Oracle 12C(2013年6月)には、次のようにそれを使用することができます。

SELECT * FROM   MYTABLE
--ORDER BY COLUMNNAME -OPTIONAL          
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY

6
興味深いコマンドです。ここでは12c OFFSET 0 ROWSを使用していますが、明らかに必要ではありません。使用することFETCH NEXT 1 ROWS ONLYもできます。FETCH FIRST ROW ONLY順序を指定することも重要WHERE rownum = 1です。OUTER APPLY命令で試してみましたが、Ms-SQLのTOP関数のように機能しました。
Rafael Merlin

あなたは正しい@RafaelMerlinです。あなたの投稿後、OFFSET 0 ROWSは必要ないことを認識しました。トップXとYのトップの間でデータを取得する際には有用であろう
MSK

1

これまでのところ、重要な不足している点がありTIESます。バージョンとの関係が発生する場合については、これを参照してください12c +12c -
BarbarosÖzhan19年

10

サブクエリで句を使用ROW_NUMBER()し、ORDER BYこの列をの代わりに使用できますTOP N。これは段階的に説明できます。

2つの列がある以下の表を参照してください NAMEDT_CREATED

ここに画像の説明を入力してください

に関係なく最初の2つの日付のみを取得する必要NAMEがある場合は、次のクエリを使用できます。ロジックはクエリ内に記述されています

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
    -- Generates numbers in a column in sequence in the order of date
    SELECT ROW_NUMBER() OVER (ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

結果

ここに画像の説明を入力してください

状況によっては、TOP Nそれぞれに対応する結果を選択する必要がありますNAME。そのような場合に使用できますPARTITION BYORDER BYサブクエリで句をます。以下のクエリを参照してください。

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
  --Generates numbers in a column in sequence in the order of date for each NAME
    SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

結果

ここに画像の説明を入力してください


1
ROW_NUMBER()...を使用することは、トピックの回答よりも正しい解決策です。このソリューション(およびmax(field)バリアントも)の1つの問題は、「select ...(select ROW_NUMBER()...)for update ;」のようなことを実行できないことです。
Alexo Po。

また、PL / SQLでは非常に重要になる場合があります(申し訳ありませんが、5分以内に以前のコメントを編集できませんでした)。
Alexo Po。

このような場合、外側と同様にCTEを使用できます。正しい?@Alexo Po。
Sarath Avanavu、2015

私はあなたを理解していないと思います。for update句は、ROWIDがOracleによって「簡単に」保存されるときに使用できます。したがって、グループ化(および分析句の使用によるグループ化)は実際のROWIDを隠し、行をロックできません。次に、CTE(with (select ... ) as 句)はこの問題に対して何も変更しません。CTEはクエリの読み取りとサポートを目的としています。正しい?@Sarath Avanavu
Po。

私自身に注意してください。ROWIDの問題は実際には特にRNO <3条件のために発生します。この場合、RNOの値はROWIDに接続されていないため、Oracleは行をロックできません。
Alexo Po。

9

あなたは次のようなことができます

    SELECT *
      FROM (SELECT Fname FROM MyTbl ORDER BY Fname )
 WHERE rownum = 1;

分析関数RANKDENSE_RANKを使用することもできますが、ROWNUMがおそらく最も簡単です。


1
ランクなどのいくつかの例を手伝っていただけませんか
breakfreehg '15

9
select * from (
    select FName from MyTbl
)
where rownum <= 1;

5

使用する:

SELECT x.*
  FROM (SELECT fname 
          FROM MyTbl) x
 WHERE ROWNUM = 1

Oracle9i +を使用している場合は、ROW_NUMBER()などの分析関数使用することもできますが、ROWNUMほどパフォーマンスはよくありません


1
いい答えですが、小さなタイプミスが含まれています。Oracle9i +が8iであってはならないというのはどこですか。download-west.oracle.com/docs/cd/A87860_01/doc/server.817/...
イアン・カーペンター

@carpenteri:確かに、分析は8iで利用可能でした-詳細を思い出せませんが、分析は実際には9iまで一般には利用できませんでした。
OMGポニー2010

小さなコメント-以下のVashの回答には、内部クエリに対するORDER BYが含まれています。これは、「最初」ではなく、fnameのTOP値が必要な場合に重要です(ほとんどの場合、最初の行が挿入されます)。編集する価値がありますか?
JulesLt 2010

@JulesLt:OPによって提供されるクエリにはORDER BYが含まれていないため、これは答えの表現であり、Oracle構文への正確な変換です。
OMGポニー2010

SQL SERVER TOP構文の誤解(ROWNUMではなくRANKのFIRSTに類似していると誤って推定した)。投票した。
JulesLt 2010

3

テーブルから最初の行を選択することと、テーブルから1つの行を選択することは2つの異なるタスクであり、異なるクエリが必要です。これを行うには多くの可能な方法があります。それらの4つは次のとおりです。

最初

select  max(Fname) from MyTbl;

二番目

select  min(Fname) from MyTbl;

第三

select  Fname from MyTbl  where rownum = 1;

第4

select  max(Fname) from MyTbl where rowid=(select  max(rowid) from MyTbl)

3

私は同じ問題を抱えていましたが、この解決策でこれを修正できます:

select a.*, rownum 
from (select Fname from MyTbl order by Fname DESC) a
where
rownum = 1

最初の値が一番上になるように、前に結果を並べ替えることができます。

幸運を

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.