Oracle SELECT TOP 10 kayıtları


144

Oracle bir SQL deyimi ile büyük bir sorun var. STORAGE_DB tarafından sipariş edilen ve başka bir select deyiminden bir listede olmayan TOP 10 kayıtlarını seçmek istiyorum.

Bu, tüm kayıtlar için iyi çalışır:

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
      STORAGE_GB IS NOT NULL AND 
        APP_ID NOT IN (SELECT APP_ID
                       FROM HISTORY
                        WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

Ama eklediğimde

AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC

Bir çeşit "rasgele" Kayıt alıyorum. Sanırım sınır siparişten önce gerçekleşiyor.

Birinin iyi bir çözümü var mı? Diğer sorun: Bu sorgu gerçekten yavaş (10k + kayıt)



Yanıtlar:


199

Mevcut sorgunuzu aşağıdaki gibi alt sorguya koymanız gerekir:

SELECT * FROM (
  SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC )
WHERE ROWNUM <= 10

Oracle , döndürüldükten sonra sonuca rownum uygular .
Sonucu döndürüldükten sonra filtrelemeniz gerekir, bu nedenle bir alt sorgu gerekir. Top-N sonuçlarını almak için RANK () işlevini de kullanabilirsiniz .

Performans NOT EXISTSiçin yerine kullanmayı deneyin NOT IN. Bkz bu daha fazlası.


NOT EXISTS bu senaryoda çalışmıyor (geçersiz ilişkisel operatör) APP_ID NOT EXISTS (SELEC ...)
— opHASnoNAME

3
Bazıları bunun insanları Oracle'a kapatmak için uygun olduğunu söyleyebilir.
— MrBoJangles

2
FETCH NEXT N ROWS ONLYAşağıdaki cevabı kontrol edin .
— Mohnish

@Padmarag: Böyle bir sorguda bir rownum ne zaman uygulanır - SomeTol'dan * seçin, burada someColumn = '123' ve rownum <= 3. [SomeTol'dan * Select * from someColumn = '123'] 'den sonuçları seçtikten sonra mı
— Shirgill Farhan

55

Oracle 12c kullanıyorsanız, şunu kullanın:

FETCH SADECE N SIRA

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC
FETCH NEXT 10 ROWS ONLY

Daha fazla bilgi: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html


2
Bu diğer cevaba göre altın
— aswzen


1
Bu yanıtı 100 yukarı vermek istiyorum! Ama ne yazık ki, sadece bir tane ödül vereceğim. Bir tane!
— Eidylon

23

Kötü performans ile ilgili olarak, olabilecek çok sayıda şey vardır ve gerçekten ayrı bir soru olmalıdır. Ancak, bir sorun olabilecek bariz bir şey var:

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

HISTORY_DATE gerçekten bir tarih sütunuysa ve bir dizini varsa, bu yeniden yazma daha iyi performans gösterir:

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')  

Bunun nedeni, bir veri türü dönüştürmesinin B-Tree dizininin kullanımını devre dışı bırakmasıdır.


22

Deneyin

SELECT * FROM users FETCH NEXT 10 ROWS ONLY;

11

Görünüşe göre rastgele bir küme alırsınız çünkü ROWNUM ORDER BY'dan önce uygulanır. Böylece, sorgunuz ilk on satırı alır ve sıralar.

 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm<=10
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.