2010-03-23 16 views
85

मुझे ओरेकल में एक SQL स्टेटमेंट के साथ एक बड़ी समस्या है। मैं STORAGE_DB द्वारा आदेशित शीर्ष 10 रिकॉर्ड्स का चयन करना चाहता हूं जो किसी अन्य चयन कथन से सूची में नहीं हैं।ओरेकल चयन शीर्ष 10 रिकॉर्ड

यह एक सभी रिकॉर्ड के लिए ठीक काम करता है:

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') 

लेकिन जब मैं

AND ROWNUM <= 10 
ORDER BY STORAGE_GB DESC 

द्वारा जोड़ा जा रहा मैं "यादृच्छिक" रिकॉर्ड्स के कुछ प्रकार हो रही है। मुझे लगता है क्योंकि आदेश से पहले सीमा तय होती है।

क्या किसी के पास कोई अच्छा समाधान है? दूसरी समस्या: इस क्वेरी वास्तव में धीमी है (10k + रिकॉर्ड)

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/2306744/oracle-sql-how-to-retrieve-highest-5-values-of-a-column – APC

उत्तर

142

आप नीचे दिए गए के रूप में सबक्वेरी में अपने वर्तमान क्वेरी डाल करने के लिए की आवश्यकता होगी:

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 

ओरेकल परिणाम पर लागू होता है rownum के बाद यह वापस आ गया है।
आपको लौटने के बाद परिणाम को फ़िल्टर करने की आवश्यकता है, इसलिए एक सबक्वायरी आवश्यक है। शीर्ष-एन परिणाम प्राप्त करने के लिए आप RANK() फ़ंक्शन का भी उपयोग कर सकते हैं।

प्रदर्शन के लिए NOT IN के स्थान पर NOT EXISTS का उपयोग करने का प्रयास करें। अधिक के लिए this देखें।

+0

EXISTS इस परिदृश्य में काम नहीं कर रहा है (अमान्य संबंधपरक ऑपरेटर) APP_ID EXISTS (SELEC ...) – opHASnoNAME

22

खराब प्रदर्शन के संबंध में यह कई चीजें हो सकती हैं, और यह वास्तव में एक अलग प्रश्न होना चाहिए।

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

तो HISTORY_DATE वास्तव में एक तारीख स्तंभ है और अगर यह एक सूचकांक है तो यह फिर से लिखने में बेहतर प्रदर्शन करेगा:

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

इसका कारण यह है है हालांकि, वहाँ एक स्पष्ट बात यह है कि एक समस्या हो सकती है है एक डेटाटाइप रूपांतरण बी-ट्री इंडेक्स के उपयोग को अक्षम करता है।

10

आपको स्पष्ट रूप से यादृच्छिक सेट मिलता है क्योंकि ROWNUM ऑर्डर द्वारा पहले लागू किया जाता है। तो आपकी क्वेरी पहली दस पंक्तियां लेती है और उन्हें टाइप करती है।0 शीर्ष दस वेतन चयन करने के लिए आप एक सबक्वेरी में एक विश्लेषणात्मक समारोह का उपयोग करना चाहिए, तो फ़िल्टर कर कि:

select * from 
    (select empno, 
      ename, 
      sal, 
      row_number() over(order by sal desc nulls last) rnm 
    from emp) 
where rnm<=10 
11

आप ओरेकल 12C उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं:

अगले एन पंक्तियों केवल लाने

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 

और जानकारी: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

+1

सरल और बिंदु पर। फ़ेच अगली 10 पंक्तियां केवल –

-4

आप कर सकते हैं बस टॉप क्लॉज

शीर्ष 10 * तालिका से चुनें;

या

चयन COLUMN_NAME (रों) TABLE_NAME से कहां ROWNUM < = संख्या;

+1

ऑरैकल एसक्यूएल में नहीं ... – Zafi

2

कोशिश करें * उपयोगकर्ताओं से केवल 10 पंक्तियों को प्राप्त करें;

+0

केवल ओरेकल 12 सी पर काम करता है और बाद में – Volpato

संबंधित मुद्दे