Bagaimana cara memilih hanya 1 baris dari oracle sql?

111

Saya ingin menggunakan sintaks oracle untuk memilih hanya 1 baris dari tabel DUAL. Misalnya, saya ingin menjalankan kueri ini:

SELECT user 
  FROM DUAL

... dan itu akan memiliki, seperti, 40 rekaman. Tapi saya hanya butuh satu catatan. ... DAN, saya ingin mewujudkannya tanpa WHEREklausul.

Saya butuh sesuatu di bidang nama_tabel seperti:

SELECT FirstRow(user) 
  FROM DUAL
Ben
sumber
1
Versi Oracle berapa? Menggunakan ROWNUM atau ROW_NUMBER (9i +) berarti membutuhkan klausa WHERE
OMG Ponies
1
Apakah Anda menamai meja dual?
ypercubeᵀᴹ
1
@ypercube dualadalah tabel sistem di oracle
4
@ Ben, Anda seharusnya tidak membuat tabel bernama DUAL. Ini seperti #define TRUE 0di C - tentu, ini mungkin berhasil untuk Anda, tetapi pengembang masa depan akan membenci Anda.
Jeffrey Kemp
3
Apakah Anda benar-benar mencoba lari select user from dual? Jika tidak, silakan coba, dan lihat apa yang Anda dapatkan. Pada sistem oracle standar, Anda akan mendapatkan kembali pengguna yang Anda gunakan untuk menjalankan perintah.
Shannon Severance

Jawaban:

170

Anda menggunakan ROWNUM.

yaitu.

SELECT user FROM Dual WHERE ROWNUM = 1

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

mindvirus
sumber
@ypercube sejauh yang saya tahu, memang begitu. (Setidaknya itu berfungsi untuk instalasi oracle10g saya.)
@bdares: itu akan berhasil, ya. Tapi bukan jawabanmu, dengan order by.
ypercubeᵀᴹ
1
Iya. ROWNUM adalah kolom khusus yang ditambahkan ke kumpulan hasil yang menghitung hasil. Anda juga dapat menggunakannya untuk memilih beberapa, misalnya, jika Anda ingin menemukan 10 karyawan dengan bayaran tertinggi, Anda dapat mengatakan "PILIH pengguna DARI Karyawan DI MANA ROWNUM <= 10 ORDER BY DESCENDING GAJI"
mindvirus
10
@mkdess: Tidak, ORDER BYditerapkan setelah WHERE.
ypercubeᵀᴹ
15
Anda membutuhkan:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ
49

Saya menemukan "solusi" ini tersembunyi di salah satu komentar. Karena saya mencarinya sebentar, saya ingin menyoroti sedikit (belum bisa berkomentar atau melakukan hal semacam itu ...), jadi inilah yang saya gunakan:

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

Ini akan mencetak saya entri [Kolom] yang diinginkan dari entri terbaru dalam tabel, dengan asumsi [Tanggal] selalu dimasukkan melalui SYSDATE.


sumber
Saya menemukan itu juga akan berfungsi jika Anda memesan dengan ROWID, selama Anda tidak pernah menghapus catatan apa pun dan selalu peduli dengan yang terakhir dimasukkan / dimodifikasi.
vapcguy
@vapcguy: Jangan berharap ROWID diurutkan, bahkan jika Anda tidak pernah menghapus baris dari tabel! Bahkan jika itu berhasil untuk Anda sekarang, itu tidak pernah dijamin akan berfungsi di versi yang akan datang.
D. Mika
@ D.Mika Sebenarnya jika berfungsi sekarang, dan Anda tidak pernah menambah / menghapus / memperbarui / menghapus catatan, seharusnya tidak akan ada masalah. Catatan hanya dapat diubah jika Anda benar-benar mengubahnya. Ada kesalahpahaman yang entah bagaimana ROWIDdimodifikasi secara acak oleh Oracle. Tidak. Ini didasarkan pada benar-benar memodifikasi baris, yaitu Anda menghapus satu, lalu menyisipkan satu. Yang dimasukkan akan mendapatkan yang lama ROWID. Ada hal-hal seperti tabel statis yang tidak pernah diperbarui-seperti negara bagian di AS adalah contoh yang baik-di mana jika berubah, mungkin akan memiliki dampak lain, bagaimanapun, ketika ini baik-baik saja.
vapcguy
@vapcguy: Yah, hampir benar. Tetapi ada operasi lain yang akan mengubah ROWID. Bagaimana jika Anda mengekspor / mengimpor tabel karena alasan tertentu? Ada operasi lain, tetapi beberapa di antaranya membutuhkan AKTIFKAN GERAKAN BARIS. Saya hanya ingin mengatakan bahwa tidak baik mengandalkan detail implementasi yang mungkin berubah di masa mendatang.
D. Mika
@ D. Mika Saya yakin jika ada operasi yang ROWIDdapat diubah, DBA yang baik akan mencarinya dan melakukan apa yang mereka bisa untuk menghindarinya jika ada kemungkinan mereka mempengaruhi tabel statis seperti yang saya jelaskan itu hanya aplikasi yang harus dioperasikan. Ekspor tabel dapat dilakukan dengan SELECTpernyataan. Impor akan terjadi sekali dan tidak akan pernah lagi. Saya mengerti maksud Anda, perhatian pasti dibutuhkan, tetapi masalahnya jauh dari tidak dapat dihindari.
vapcguy
35

Sintaks ini tersedia di 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;

^^ Saya hanya ingin menunjukkan bahwa baik baris atau baris (jamak) dapat digunakan terlepas dari pluralitas jumlah baris yang diinginkan.)

mancini0
sumber
1
pilih * dari some_table ambil 1 baris pertama saja; itu tidak bekerja di devloper swl saya maupun di sql plus jadi kesalahan saat mengambil.
nikhil sugandh
Apakah Anda menggunakan oracle 12c?
mancini0
saya tidak benar-benar tahu tetapi ketika saya membukanya terlihat seperti ini: SQL * PLus Release 10.1.0.4.2 bukankah 12 c
nikhil sugandh
benar - Anda menggunakan kemungkinan menggunakan versi 10.1.xxx, Anda dapat MEMILIH * DARI V $ VERSION
mancini0
10

kami memiliki 3 pilihan untuk mendapatkan baris pertama dalam tabel Oracle DB.

1) select * from table_name where rownum= 1adalah cara terbaik

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
Deva
sumber
Terima kasih atas jawabannya: di bawah poin 3) "nowrum = 1" mungkin harus diubah menjadi "rownum = 1".
Andre Nel
7

Sejauh yang saya tahu, dualtabel di Oracle adalah tabel khusus dengan hanya satu baris. Jadi, ini sudah cukup:

SELECT user
FROM dual
ypercubeᵀᴹ
sumber
itu tidak benar pilih pengguna dari ganda harus memberikan semua pengguna
Ben
1
.. dan baru saja mencoba sistem saya, berfungsi sebagai ypercube & semua dokumentasi terkait yang disebutkan. @Ben
Syaj Bhat
1
@Ben dual bukan tampilan katalog, ini tidak akan menampilkan "semua pengguna". Anda akan menggunakan tampilan seperti ALL_USERS untuk tujuan itu.
mulai
7

👌 Jawabannya adalah:

Anda harus menggunakan kueri bersarang sebagai:

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

=> Dalam PL / SQL "ROWNUM = 1" TIDAK sama dengan "TOP 1" dari TSQL.

Jadi, Anda tidak dapat menggunakan kueri seperti ini: "pilih * dari any_table_x di mana rownum = 1 pesanan oleh any_column_x;" Karena oracle mendapat baris pertama maka berlaku order by clause.

Fuat
sumber
1
Harap tambahkan beberapa klarifikasi pada jawaban Anda
hgwhittle
Sintaks yang tidak biasa harus dihindari tanpa alasan yang kuat. Dalam kasus ini, akan sangat membantu jika memberikan kasus uji atau nomor bug. Saya samar-samar mengingat beberapa masalah aneh dengan rownum = 1, tetapi kita tidak boleh membiarkan bug lama memengaruhi kode kita lagi.
Jon Heller
7
@hgwhittle, Alasan mengapa Fuat benar adalah karena ROWNUM tidak peduli dengan 'ordery by', ia hanya mengambil record pertama yang dapat ditemukannya dan segera mengembalikannya. Jadi dengan kata lain, qualifier ROWNUM tidak menghormati perintah "Order By". Saya berharap bukan itu masalahnya tetapi Fuat benar, untuk menggunakan kueri bersarang.
Eric Milliot-Martinez
5

Tidak ada limit 1kondisi (itu MySQL / PostgresSQL) di Oracle, Anda perlu menentukan where rownum = 1.

Oh Chin Boon
sumber
5

"FirstRow" Adalah batasan dan oleh karena itu ditempatkan di whereklausa bukan di selectklausa. Dan itu disebut rownum

select * from dual where rownum = 1;
gdoron mendukung Monica
sumber
1
Perhatikan bahwa ini tidak akan bekerja seperti yang diharapkan dalam kombinasi dengan ORDER BY, karena pengurutan hanya terjadi setelah klausa where. Dengan kata lain, untuk mendapatkan urutan teratas dari kueri yang diurutkan tertentu, rownum sama sekali tidak berguna.
Nyerguds
@Nyerguds, ini hanya setengah benar. Anda dapat menggunakan order by before Wheredengan kueri View.
gdoron mendukung Monica
4
Jadi apa SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Yah, itu mungkin berhasil, tapi kelihatannya cukup bodoh, tbh.
Nyerguds
2

Jika ada baris yang cocok, coba:

select max(user)  
from table;

Tidak ada klausul di mana.

Raihan
sumber
9
Tentunya hanya perlu beberapa detik bagi Anda untuk mencobanya sendiri
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; 
Andrew
sumber
1

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

akan melakukan yang terbaik, opsi lainnya adalah:

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

dalam skenario di mana Anda menginginkan subset yang berbeda, tetapi saya rasa Anda juga bisa menggunakan RANK()Tapi, saya juga suka row_number() over(...)karena tidak diperlukan pengelompokan.

Tyler
sumber
0

Jika Anda ingin mendapatkan kembali hanya baris pertama dari hasil yang diurutkan dengan subkueri paling sedikit, coba ini:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;
Jody Fedor
sumber
Di mana sysdate_col akan menjadi nama kolom apa pun yang ingin Anda urutkan dan tentu saja, nama_tabel akan menjadi nama tabel yang Anda inginkan untuk mendapatkan data yang diurutkan.
Jody Fedor
-1

Lebih fleksibel daripada select max():

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Tamu
sumber