Oracle'da ilk 1'i nasıl yapabilirim?


251

Aşağıdakileri nasıl yaparım?

select top 1 Fname from MyTbl

In Oracle 11g ?




3
Bize 'ilk 1' istediğiniz siparişi söyleyebilir misiniz?
Andrew Wolfe

1
Her şeyden önce bunu yapmak için DB motoruna asla güvenmemelisiniz. Bunun gibi şeyleri bilmek istiyorsanız, bir sıralayıcı koyun. Bunu yaptığınızda, yerleştirildikleri sıraya göre numaralandırılacakları garanti edilir.
FlyingGuy

Yanıtlar:


257

Yalnızca ilk seçilen satırı istiyorsanız, şunları yapabilirsiniz:

select fname from MyTbl where rownum = 1

Üstteki x'i sıralamak ve almak için analitik işlevleri de kullanabilirsiniz:

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

54
Bu sadece 1 satır istiyorsanız ve hangisini umursamıyorsanız iyi olur. En son kayıt gibi belirli satırlar istiyorsanız, sıralamayı Vash'ın yanıtı gibi bir alt seçimle yapmanız gerekir. Oracle sıralamadan önce rownum atar.
Scott Bailey

4
@Yapı yup. bu doğru. Ve Patrick, iyi bir nokta bence sözdizimi yanlış. Gerçekten bir tutmak olmalı (dense_rank () son ...)
mcpeterson

2
Birinci ve ikinci örnek arasındaki fark, birincinin A satırını (sıra olmadan herhangi bir satır) seçmesidir. İkinci örnek, bir sipariş iç sorgusu yapmadan ilk satırın değerini alır (aşağıdaki örneklere göre).
JulesLt

3
MyTbl seçin max (fname) üzerinden (some_factor tarafından rank () sırayla): değil doğru içinde sözdizimi
Stéphane Gerber

1
@jclozano "oracle'in çok iyi bilinen bir işlevselliği değil" - Saygılarımla, farklı olmaya yalvarıyorum. Bu önemlidir çünkü "iyi bilinmeyen işlevsellik" belirsizliği ima etme eğilimindedir ve bu nedenle kullanmaktan kaçınmamız gerektiğini önerebilir. Bu belirsiz değildir ve kullanımından kaçınılmamalıdır.
Mart'ta Sepster

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

8
Bu yanıt TOP satırını doğru bir şekilde alır (ROWNUM üzerinde kısıtlamadan önce sonuçları sıralar).
JulesLt

Bu yanıt tam bir çeviri değildir - orijinal sorgunun ORDER BY değeri yoktur ve tablodaki tüm sütunları döndürmez.
OMG Ponies

Düzeltilmiş duruyorum (aşağıya bakın). Zaman dolduğunda oy değiştirir.
JulesLt

7
@OMGPonies evet. ama büyük olasılıkla çoğu kişi aslında bu sayfaya sorununu googling ile gelen istediği
şeydir

4
Kesinlikle bu konudaki kazanan cevap olmalı. top XBiri için bunu değiştirebilir bir not ekleyebilirWHERE ROWNUM <= X
SomethingSomething 23

31

İle Oracle 12c (Haziran 2013), aşağıdakilerden gibi kullanmak mümkün.

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

6
İlginç bir komut, burada 12c kullanıyorum ve OFFSET 0 ROWSgörünüşte gerekli değil, kullanabilirsiniz FETCH NEXT 1 ROWS ONLYveya hatta FETCH FIRST ROW ONLY, sipariş önemlidir veya sadece a kullanmaya eşdeğer olacaktır WHERE rownum = 1. Hatta bir OUTER UYGULAMA talimatı denedim ve orada Ms-SQL TOP işlevi gibi çalıştı.
Rafael Merlin

Haklısın @RafaelMerlin. Gönderinizden sonra OFSET 0 ROWS'un gerekli olmadığını anladım. Üst X ve üst Y arasında veri alınırken yararlı olacaktır
MSK


Şimdiye kadar çok iyi, önemli bir eksik noktası olan TIES. Bakın bu bağları sürümü için ortaya çıktığında durumlarda 12c +ve12c -
Barbaros Özhan

10

Alt sorguda ROW_NUMBER()bir ORDER BYcümle ile kullanabilir ve bunun yerine bu sütunu kullanabilirsiniz TOP N. Bu adım adım açıklanabilir.

İki sütun NAMEve içeren aşağıdaki tabloya bakın DT_CREATED.

resim açıklamasını buraya girin

Ne olursa olsun, yalnızca ilk iki tarihi almanız gerekiyorsa NAME, aşağıdaki sorguyu kullanabilirsiniz. Mantık sorgunun içine yazılmıştır

-- 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;

SONUÇ

resim açıklamasını buraya girin

Bazı durumlarda, TOP Nher biriyle ilgili sonuçları seçmemiz gerekir NAME. Bu durumda alt sorguda PARTITION BYbir ORDER BYcümle ile birlikte kullanabiliriz . Aşağıdaki sorguyu inceleyin.

-- 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;

SONUÇ

resim açıklamasını buraya girin


1
ROW_NUMBER () ... kullanmak konu cevabından daha doğru bir çözümdür. Güncelleme için "select ... (ROW_NUMBER () ...) ;";
Alexo Po.

Ve PL / SQL'de bazen çok önemlidir (üzgünüm, önceki yorumu 5 dakika limitinde düzenleyemedi).
Alexo Po.

Bu durumda CTE'yi dış kısımdaki gibi kullanabiliriz. Sağ? @Alexo Po.
Sarath Avanavu

Sanırım seni anlamıyorum. Güncelleme cümlesi, ROWID Oracle tarafından "kolayca" korunduğunda kullanılabilir. Dolayısıyla gruplama (ve analitik yan tümce kullanımı nedeniyle gruplama) gerçek ROWID değerini gizler ve satırlar kilitlenemez. İkincisi, CTE ( with (select ... ) as fıkra) bu soruna hiçbir şey değiştirmez, CTE sadece sorguları okumayı ve desteklemeyi amaçlar. Sağ? @Sarath Avanavu
Alexo Po.

Kendime not. ROWID ile ilgili sorun aslında özellikle RNO <3 koşulunun olduğu için oluşur, bu durumda RNO değeri ROWID ile bağlı değildir, bu nedenle Oracle satırları kilitleyemez.
Alexo Po.

9

Gibi bir şey yapabilirsin

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

Analitik fonksiyonları RANK ve / veya DENSE_RANK da kullanabilirsiniz , ancak ROWNUM muhtemelen en kolay olanıdır .


1
rütbe vb bazı örnek ile yardımcı olabilir misiniz
breakfreehg

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

5

kullanın:

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

Oracle9i + kullanıyorsanız, ROW_NUMBER () gibi analitik işlevleri kullanmaya bakabilirsiniz, ancak ROWNUM kadar iyi performans göstermezler .


1
Güzel cevap ama küçük bir yazım hatası içeriyor. Oracle9i + dediğiniz yerde 8i olmamalı? download-west.oracle.com/docs/cd/A87860_01/doc/server.817/…
Ian Carpenter

@carpenteri: Doğru, analizler 8i'de mevcuttu - ayrıntılarını hatırlayamıyorum, ancak analizler 9i'ye kadar gerçekten halka açık değildi.
OMG Ponies

Küçük yorum - Vash'in aşağıdaki cevabı, iç sorguda 'ilk' (örneğin, herhangi bir şey olabilir, büyük olasılıkla ilk satır eklenmiş) yerine fname'nin TOP değerini istiyorsanız kritik olan bir ORDER BY içerir. Düzenlemeye değer olabilir mi?
JulesLt

@JulesLt: OP tarafından sağlanan sorgu ORDER BY içermez, bu yüzden bu cevap Oracle sözdizimine tam olarak temsil eder.
OMG Ponies

SQL SERVER TOP sözdizimini yanlış anladım (yanlışlıkla ROWNUM'daki RANK içindeki FIRST ile benzer olduğu varsayıldı). Oy verildi.
JulesLt

3

Bir tablodan ilk satırı seçmek ve bir tablodan bir satır seçmek için iki farklı görev vardır ve farklı bir sorgu gerekir. Bunu yapmanın birçok yolu vardır. Bunlardan dördü:

İlk

select  max(Fname) from MyTbl;

İkinci

select  min(Fname) from MyTbl;

Üçüncü

select  Fname from MyTbl  where rownum = 1;

Dördüncü

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

3

Aynı sorunu yaşadım ve bunu bu çözümle düzeltebilirim:

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

İlk değeri en üstte tutmak için sonucunuzu sipariş edebilirsiniz.

İyi şanslar

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.