Oracle sql'den sadece 1 satır nasıl seçilir?


111

Tablodan yalnızca 1 satır seçmek için oracle sözdizimini kullanmak istiyorum DUAL. Örneğin, şu sorguyu yürütmek istiyorum:

SELECT user 
  FROM DUAL

... ve yaklaşık 40 kaydı olacaktı. Ama sadece bir kayda ihtiyacım var. ... VE bunu bir WHEREmadde olmadan gerçekleştirmek istiyorum .

Table_name alanında şunun gibi bir şeye ihtiyacım var:

SELECT FirstRow(user) 
  FROM DUAL

1
Oracle'ın hangi sürümü? ROWNUM veya ROW_NUMBER (9i +) kullanmak bir WHERE yan tümcesine ihtiyaç duymak anlamına gelir
OMG Ponies

1
Bir masa isimlendirdin dualmi?
ypercubeᵀᴹ

1
@ypercube oracle'daki dualsistem tablosudur

4
@Ben, gerçekten adında bir tablo oluşturmamalısın DUAL. Biraz #define TRUE 0C'deki gibi - tabii, sizin için işe yarayabilir, ancak gelecekteki geliştiriciler sizden nefret edecek.
Jeffrey Kemp

3
Gerçekten koşmayı denedin select user from dualmi? Değilse, lütfen bunu deneyin ve ne elde ettiğinizi görün. Standart bir oracle sisteminde, komutu birlikte yürüttüğünüz kullanıcıyı geri alacaksınız.
Shannon Kıdemliliği

Yanıtlar:


170

ROWNUM kullanıyorsunuz.

yani.

SELECT user FROM Dual WHERE ROWNUM = 1

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


@ypercube anlayabildiğim kadarıyla, öyle. (En azından oracle10g kurulumum için çalışıyor.)

@bdares: işe yarayacak, evet. Ama cevabınız değil order by.
ypercubeᵀᴹ

1
Evet. ROWNUM, sonuçları numaralandıran sonuç kümesine eklenen özel bir sütundur. Birden fazla kişi seçmek için de kullanabilirsiniz, örneğin, en çok maaş alan 10 çalışanı bulmak istiyorsanız, "SİPARİŞ
VEREN

10
@mkdess: Hayır, ORDER BYsonra uygulanır WHERE.
ypercubeᵀᴹ

15
İhtiyacınız olan:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

49

Bu "çözümü" yorumlardan birinde saklı buldum. Bir süredir aradığım için, biraz vurgulamak istiyorum (henüz yorum yapamam veya böyle şeyler yapamam ...), bu yüzden kullandım:

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

Bu, [Tarih] 'in her zaman SYSDATE aracılığıyla eklendiğini varsayarak, tablodaki en yeni girişten istenen [Sütun] girişini yazdıracaktır.


ROWIDHiçbir kaydı silmediğiniz ve her zaman son eklenen / değiştirileni önemsediğiniz sürece, sipariş verirseniz de işe yarayacağını gördüm .
vapcguy

@vapcguy: Tablodan bir satırı silmeseniz bile ROWID'in sıralanmasını beklemeyin! Şu anda sizin için çalışsa bile, gelecekteki sürümlerde çalışacağı asla garanti edilmez.
D. Mika

@ D.Mika Aslında şu anda çalışıyorsa ve asla kayıt ekleme / çıkarma / güncelleme / silme işlemi yapmıyorsanız, hiçbir zaman sorun olmamalıdır. Kayıtlar yalnızca onları gerçekten değiştirirseniz değiştirilebilir. ROWIDOracle tarafından bir şekilde rastgele değiştirildiği şeklinde bir yanlış anlama var . Değil. Aslında satırları değiştirmeye dayanır, yani birini silip bir tane eklersiniz. Takılan, eskisininkini alacaktır ROWID. ABD'de hiçbir zaman güncellenen benzeri durumlar almayan statik tablolar gibi şeyler iyi bir örnektir - eğer değişirse, bu iyi olduğunda muhtemelen başka yansımaları olacaktır.
vapcguy

@vapcguy: Bu neredeyse doğru. Ancak ROWID'yi değiştirecek başka işlemler de var. Ya herhangi bir nedenle tabloyu dışa / içe aktarırsanız? Başka işlemler var, ancak bazılarının SATIR HAREKETİNİ ETKİNLEŞTİR'e ihtiyacı var. Gelecekte değişebilecek bir uygulama ayrıntısına güvenmenin iyi bir fikir olmadığını söylemek istiyorum.
D. Mika

@ D.Mika Eminim ki ROWIDdeğiştirilebilecek herhangi bir işlem varsa , iyi bir DBA onları arar ve anlattığım gibi statik bir tabloyu etkileme olasılığı varsa onlardan kaçınmak için ellerinden geleni yapar. yalnızca uygulama üzerinde çalışıyor olmalıdır. Bunun SELECTyerine bir tablo dışa aktarımı bir ifade ile yapılabilir . İçe aktarma bir kez olur ve sonra bir daha asla olmaz. Demek istediğini anlıyorum, bakıma kesinlikle ihtiyaç var, ancak sorunlar kaçınılmaz olmaktan uzak.
vapcguy

35

Bu sözdizimi Oracle 12c'de mevcuttur:

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;

^^ Sadece satırların veya satırların (çoğul) istenen sayıda satır sayısından bağımsız olarak kullanılabileceğini göstermek istedim.)


1
Yalnızca bazı tablolardan * ilk 1 satırı getir; benim swl geliştiricimde ve sql'de çalışmıyor artı getirmede hata var.
nikhil sugandh

Oracle 12c kullanıyor musunuz?
mancini 0

gerçekten bilmiyorum ama
açtığımda

doğru - muhtemelen 10.1.xxx sürümünü kullanıyorsunuz, V $
VERSION'DAN

10

Oracle DB tablosundaki ilk satırı almak için 3 seçeneğimiz var.

1) select * from table_name where rownum= 1en iyi yoldur

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

Cevaplar için teşekkürler: 3. maddede) "nowrum = 1" muhtemelen "rownum = 1" olarak değiştirilmelidir.
Andre Nel

7

Bildiğim kadarıyla dualOracle'daki tablo tek satırlık özel bir tablodur. Yani bu yeterli olacaktır:

SELECT user
FROM dual

bu doğru değil, dual'den seçilen kullanıcı size tüm kullanıcıları vermeli
Ben


1
.. ve sistemimde yeni denedim, ypercube ve ilgili tüm dokümantasyon olarak çalışıyor. @Ben
Sathyajith Bhat

1
@Ben dual bir katalog görünümü değildir, "tüm kullanıcıları" göstermez. Bunun için ALL_USERS gibi bir görünüm kullanırsınız.
makrom

7

👌 Cevap:

İç içe geçmiş sorguyu şu şekilde kullanmalısınız:

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

=> PL / SQL'de "ROWNUM = 1", TSQL'in "TOP 1" e eşit DEĞİLDİR.

Dolayısıyla, bunun gibi bir sorgu kullanamazsınız: "any_table_x'ten * seçin; burada rownum = any_column_x'e göre 1 sipariş;" Çünkü oracle ilk satırı alır ve sonra cümlecik sırayla uygular.


1
Lütfen cevabınıza biraz açıklama ekleyin
hgwhittle

Olağandışı sözdiziminden iyi bir neden olmadan kaçınılmalıdır. Bu durumda, bir test durumu veya bir hata numarası sağlamak faydalı olacaktır. Bazı tuhaf sorunları belli belirsiz hatırlıyorum rownum = 1, ancak artık eski hataların kodumuzu etkilemesine izin vermemeliyiz.
Jon Heller

7
@hgwhittle, Fuat'ın doğru olmasının nedeni, ROWNUM'un 'sıralı' ile ilgilenmemesi, bulabildiği ilk kaydı alır ve hemen geri verir. Diğer bir deyişle, ROWNUM niteleyicisinin "Sırala" komutuna saygısı yoktur. Keşke böyle olmasaydı ama Fuat doğru, iç içe sorgu kullanmak.
Eric Milliot-Martinez

5

limit 1Oracle'da herhangi bir koşul (bu MySQL / PostgresSQL) yoktur, belirtmeniz gerekir where rownum = 1.


5

"FirstRow" bir kısıtlamadır ve bu nedenle wheremaddede değil selectmaddede yer alır. Ve buna rownum deniyor

select * from dual where rownum = 1;

1
ORDER BYSıralama yalnızca where cümlesinden sonra gerçekleştiğinden, bunun ile birlikte beklendiği gibi çalışmayacağını unutmayın . Başka bir deyişle, belirli bir sıralı sorgunun üst kısmına ulaşmak için rownum tamamen yararsızdır.
Nyerguds

@Nyerguds, bu sadece yarısı doğru. WhereBir Görünüm sorgusuyla öncesinde sıralamayı kullanabilirsiniz .
gdoron Monica'yı

4
Ne yani SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Bu işe yarayabilir, ama oldukça aptalca görünüyor, tbh.
Nyerguds

2

Herhangi bir satır varsa, şunu deneyin:

select max(user)  
from table;

Nerede fıkra yok.


9
Elbette bunu kendiniz denemeniz sadece birkaç saniyenizi alacak
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

en iyi performansı gösterir, başka bir seçenek de:

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

farklı alt kümeler istediğiniz senaryolarda, ancak bunu da kullanabilirsiniz sanırım RANK()Ama, ayrıca row_number() over(...)gruplama gerekmediği için seviyorum .


0

En az alt sorguya sahip sıralanmış bir sonucun yalnızca ilk satırını geri almak istiyorsanız, şunu deneyin:

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

Burada sysdate_col, sıralamak istediğiniz herhangi bir sütunun adı olacaktır ve tabii ki tablo_adı, sıralanan verilerin gelmesini istediğiniz tablonun adı olacaktır.
Jody Fedor

-1

Olduğundan daha esnek select max():

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.