Oracle SQLから1行のみを選択する方法は?


110

Oracleの構文を使用して、テーブルから1行のみを選択しますDUAL。たとえば、次のクエリを実行したいとします。

SELECT user 
  FROM DUAL

...そして、それは、例えば、40のレコードを持っているでしょう。しかし、必要なレコードは1つだけです。...そして、私はそれをWHERE条項なしで実現させたいのです。

table_nameフィールドに次のようなものが必要です。

SELECT FirstRow(user) 
  FROM DUAL

1
Oracleのバージョンは?ROWNUMまたはROW_NUMBER(9i +)を使用すると、WHERE句が必要になります
OMGポニー2012年

1
テーブルに名前を付けましたdualか?
ypercubeᵀᴹ

1
@ypercubeは、dualオラクルのシステム・テーブルである

4
@ベン、というテーブルを作成してはいけませんDUAL#define TRUE 0Cと少し似ています-確かにうまくいくかもしれませんが、将来の開発者はあなたを嫌います。
ジェフリーケンプ

3
実際に実行してみましたselect user from dualか?そうでない場合は、それを試して、何が得られるかを確認してください。標準のOracleシステムでは、コマンドを実行しているユーザーが返されます。
シャノン退職2012年

回答:


169

ROWNUMを使用します。

すなわち。

SELECT user FROM Dual WHERE ROWNUM = 1

http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm


@ypercubeは、私が知る限り、そうです。(少なくとも、私のoracle10gのインストールでは機能します。)

@bdares:動作します、はい。しかし、あなたの答えではありませんorder by
ypercubeᵀᴹ

1
はい。ROWNUMは、結果を列挙する結果セットに追加される特別な列です。これを使用して複数を選択することもできます。たとえば、最も給与の高い10人の従業員を検索する場合、「SELECT user FROM Employees WHERE ROWNUM <= 10 ORDER BY SALARY DESCENDING」
mindvirus

10
@mkdess:いいえ、のORDER BY後に適用されますWHERE
ypercubeᵀᴹ

15
あなたは、必要があるでしょう:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

49

この「解決策」はコメントの1つに隠されていました。しばらく調べていたので、少し強調したいので(まだコメントしたり、そのようなことはできません...)、これを使用しました。

SELECT * FROM (SELECT [Column] FROM [Table] ORDER BY [Date] DESC) WHERE ROWNUM = 1

これにより、[日付]が常にSYSDATEを介して挿入されると想定して、テーブルの最新のエントリから目的の[列]エントリが出力されます。


ROWIDレコードを削除せず、常に最後に挿入/変更されたレコードを気にしない限り、で注文した場合にも機能します。
vapcguy 2016年

@vapcguy:テーブルから行を削除しない場合でも、ROWIDが順序付けされることを期待しないでください。今のところ機能する場合でも、将来のバージョンで機能することは保証されていません。
D.ミカ

@ D.Mika実際にそれが機能し、レコードを追加/削除/更新/削除しない場合、問題はありません。レコードは、実際に変更した場合にのみ変更できます。この誤解ROWIDは、Oracleによって何らかの方法でランダムに変更されるというものです。そうではありません。これは、実際に行を変更することに基づいています。つまり、行を削除してから挿入します。挿入されたものは古いものを取得しROWIDます。米国では更新されたような状態にならない静的テーブルなどの良い例があります。変更されたとしても、問題がなければ、おそらく他の影響があります。
vapcguy

@vapcguy:まあ、それはほぼ正しい。ただし、ROWIDを変更する操作は他にもあります。何らかの理由でテーブルをエクスポート/インポートするとどうなりますか?他にも操作がありますが、一部にはENABLE ROW MOVEMENTが必要です。将来変更される可能性のある実装の詳細に依存するのは良い考えではないと言いたいだけです。
D.ミカ

@ D.Mika ROWID変更可能な操作があるかどうかは確かですが、優れたDBAはそれらを調べて、静的テーブルに影響を与えている可能性がある場合は、それらを回避するためにできることを行います。アプリケーションのみが動作している必要があります。SELECT代わりに、ステートメントを使用してテーブルをエクスポートできます。インポートは一度だけ行われ、その後は二度と行われません。私はあなたの要点を理解します、注意は絶対に必要ですが、問題は避けられないというほどではありません。
vapcguy

35

この構文は、Oracle 12cで使用できます。

select * from some_table fetch first 1 row only;
select * from some_table fetch first 1 rows only;
select * from some_table fetch first 10 row only;
select * from some_table fetch first 10 rows only;

^^希望する行数の複数に関係なく、1つまたは複数の行(複数)を使用できることを示したかっただけです。)


1
select * from some_tableは最初の1行のみをフェッチします。それは私のswl devloperでもsql plusでも機能しないため、フェッチ時にエラーが発生します。
nikhil sugandh

Oracle 12cを使用していますか?
mancini0

本当にわかりませんが、開くと次のように表示されます。SQL* PLusリリース10.1.0.4.2は12 cではありません
nikhil sugandh

正解-バージョン10.1.xxxを使用している可能性があります。SELECT* FROM V $ VERSION
mancini0

10

Oracle DBテーブルの最初の行を取得するには、3つの選択肢があります。

1)select * from table_name where rownum= 1が最善の方法

2) select * from table_name where id = ( select min(id) from table_name)

3)

select * from 
    (select * from table_name order by id)
where rownum = 1

回答をありがとう:ポイント3)の下で、「nowrum = 1」は「rownum = 1」に変更する必要があります。
Andre Nel

7

私の知る限りdual、Oracle のテーブルは1行だけの特別なテーブルです。したがって、これで十分です:

SELECT user
FROM dual

それは真実ではありません。デュアルからの選択ユーザーはすべてのユーザーを提供するはずです
Ben


1
..そして、私のシステムで試してみただけで、ypercubeおよびすべての関連ドキュメントの言及として機能します。@ベン
Sathyajith Bhat 2012

1
@Ben dualはカタログビューではなく、「すべてのユーザー」を表示しません。そのためには、ALL_USERSのようなビューを使用します。
makrom

7

👌答えは:

ネストされたクエリは次のように使用する必要があります。

SELECT *
FROM ANY_TABLE_X 
WHERE ANY_COLUMN_X = (SELECT MAX(ANY_COLUMN_X) FROM ANY_TABLE_X) 

=> PL / SQLでは、「ROWNUM = 1」はTSQLの「TOP 1」と等しくありません。

したがって、「select * from any_table_x where rownum = 1 order by any_column_x;」のようなクエリは使用できません。oracleは最初の行を取得するため、order by句が適用されます。


1
回答に説明を追加してください
hgwhittle

異常な構文は、正当な理由なしに回避されるべきです。この場合、テストケースまたはバグ番号を提供すると役立ちます。私は漠然とに関するいくつかの奇妙な問題を思い出しますがrownum = 1、古いバグがコードに影響を与えることはもうありません。
Jon Heller

7
@ hgwhittle、Fuatが正しい理由は、ROWNUMが「ordery by」を気にしないためです。ROWNUMは、最初に見つけたレコードを取得し、すぐにそれを返します。したがって、言い換えると、ROWNUM修飾子は「Order By」コマンドを考慮しません。ネストされたクエリを使用する場合、そうではなかったと思いますが、Fuatは正しいです。
Eric Milliot-Martinez 2016

5

ありません limit 1Oracleに条件(MySQL / PostgresSQL)がないため、を指定する必要がありますwhere rownum = 1


5

「FirstRow」は制限であるため、where条項ではなく条項に配置されselectます。そしてそれはrownumと呼ばれています

select * from dual where rownum = 1;

1
where句の後にORDER BYのみ順序付けが行われるため、これはと組み合わせて期待どおりに機能しないことに注意してください。つまり、特定のソート済みクエリの上位を取得するために、rownumはまったく役に立たないのです。
Nyerguds 2013年

@Nyerguds、これは真実の半分だけです。並べ替えWhereは、ビュークエリの前に使用できます。
gdoronは2013

4
なんでSELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1?まあ、それはうまくいくかもしれませんが、それはかなりばかげています。
Nyerguds 2013年

2

行がある場合は、次のことを試してください。

select max(user)  
from table;

where句はありません。


9
きっと数秒で試してみることができます
Matt Donnan

1
select name, price
  from (
    select name, price, 
    row_number() over (order by price) r
      from items
  )
where r between 1 and 5; 

1

select a.user from (select user from users order by user) a where rownum = 1

最高のパフォーマンスを発揮します。別のオプションは次のとおりです。

select a.user 
from ( 
select user, 
row_number() over (order by user) user_rank, 
row_number() over (partition by dept order by user) user_dept_rank 
from users 
) a 
where a.user_rank = 1 or user_dept_rank = 2

異なるサブセットが必要なシナリオで、RANK()ただし、使用することもできると思いますがrow_number() over(...)、グループ化が必要ないため、私も好きです。


0

最小のサブクエリでソートされた結果の最初の行のみを取得したい場合は、これを試してください:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;

sysdate_colは、並べ替えに使用する任意の列の名前です。もちろん、table_nameは、並べ替えられたデータを取得するテーブルの名前です。
Jody Fedor

-1

よりも柔軟select max()

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