Oracle ORDER BY और ROWNUM का सही उपयोग कैसे करें?


126

मैं अपने उत्पाद को इसके साथ संगत करने के लिए SQL सर्वर से Oracle में संग्रहीत कार्यविधियों को परिवर्तित करने में कठिन समय बिता रहा हूं।

मेरे पास कुछ सवाल हैं जो टाइमस्टैम्प पर आधारित कुछ तालिकाओं के सबसे हालिया रिकॉर्ड को लौटाते हैं:

एस क्यू एल सर्वर:

SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC

=> जो मुझे सबसे हालिया रिकॉर्ड लौटाएगा

लेकिन ओरेकल:

SELECT *
FROM raceway_input_labo 
WHERE  rownum <= 1
ORDER BY t_stamp DESC

=> यह ORDER BYकथन की परवाह किए बिना मुझे सबसे पुराना रिकॉर्ड (शायद सूचकांक के आधार पर) लौटाएगा !

मैंने अपनी आवश्यकताओं से मेल खाने के लिए Oracle क्वेरी को इस तरह समझाया:

SELECT * 
FROM 
    (SELECT *
     FROM raceway_input_labo 
     ORDER BY t_stamp DESC)
WHERE  rownum <= 1

और यह काम करता है। लेकिन यह मेरे लिए एक भयानक हैक की तरह लगता है, खासकर अगर मेरे पास शामिल तालिकाओं में बहुत सारे रिकॉर्ड हैं।

इस लक्ष्य को हासिल करने का सबसे अच्छा तरीका क्या है ?



4
आपने अपने अंतिम प्रश्न में जो किया है वह सही है। आप रिकॉर्ड की ऑर्डर की गई सूची की पहली पंक्ति का चयन करें। बस क्वेरी एनकैप्सुलेशन।
araknoid

1
यह मैन्युअल रूप से स्पष्ट रूप से प्रलेखित है: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name

5
@a_horse_with_no_name इस 404 त्रुटि में आप स्पष्ट रूप से प्रलेखित हैं।
एंथोनीब्रिस

3
@anthonybrice: धन्यवाद। Oracle ने अपने सभी URL को मैनुअल में बदल दिया। अप-टू-डेट लिंक है: docs.oracle.com/cd/E11882_01/server.112/e41084/…
a_horse_with_no_name

जवाबों:


120

whereबयान निष्पादित हो जाता है से पहलेorder by । तो, आपकी इच्छित क्वेरी कह रही है " पहली पंक्ति ले लो और फिर इसे t_stamp डीएससी द्वारा ऑर्डर करें "। और यह वह नहीं है जो आप चाहते हैं।

ओरेकल में ऐसा करने के लिए उप-विधि विधि उचित विधि है।

यदि आप एक ऐसा संस्करण चाहते हैं जो दोनों सर्वरों में काम करे, तो आप इसका उपयोग कर सकते हैं:

select ril.*
from (select ril.*, row_number() over (order by t_stamp desc) as seqnum
      from raceway_input_labo ril
     ) ril
where seqnum = 1

बाहरी *अंतिम कॉलम में "1" लौटेगा। इससे बचने के लिए आपको कॉलम को व्यक्तिगत रूप से सूचीबद्ध करना होगा।


40

ROW_NUMBER()इसके बजाय उपयोग करें । ROWNUMएक छद्म चॉकलेट है और ROW_NUMBER()एक कार्य है। आप उनके बीच अंतर के बारे में पढ़ सकते हैं और नीचे दिए गए प्रश्नों के उत्पादन में अंतर देख सकते हैं:

SELECT * FROM (SELECT rownum, deptno, ename
           FROM scott.emp
        ORDER BY deptno
       )
 WHERE rownum <= 3
 /

ROWNUM    DEPTNO    ENAME
---------------------------
 7        10    CLARK
 14       10    MILLER
 9        10    KING


 SELECT * FROM 
 (
  SELECT deptno, ename
       , ROW_NUMBER() OVER (ORDER BY deptno) rno
  FROM scott.emp
 ORDER BY deptno
 )
WHERE rno <= 3
/

DEPTNO    ENAME    RNO
-------------------------
10    CLARK        1
10    MILLER       2
10    KING         3

3
ROWNUMतेजी से हो सकता है ROW_NUMBER()या नहीं, एक का उपयोग करना चाहिए एक से अधिक कारकों की एक संख्या पर निर्भर करता है।
डेविड फेबर

गलती के लिए माफी माँगता हूँ गलती से! दुर्भाग्य से मैं इसे अब वापस नहीं ले सकता।
अथाफौद

0

एक वैकल्पिक मैं इस उपयोग के मामले में सुझाव दूंगा कि नवीनतम पंक्ति प्राप्त करने के लिए MAX (t_stamp) का उपयोग किया जाए ... उदा

select t.* from raceway_input_labo t
where t.t_stamp = (select max(t_stamp) from raceway_input_labo) 
limit 1

मेरी कोडिंग पैटर्न वरीयता (शायद) - विश्वसनीय, आम तौर पर एक क्रमबद्ध सूची से पहली पंक्ति का चयन करने की कोशिश से बेहतर या बेहतर प्रदर्शन करता है - यह भी इरादा अधिक स्पष्ट रूप से पठनीय है।
उम्मीद है की यह मदद करेगा ...

SQLer


3
Oracle में कोई LIMIT नहीं है। आप सवाल से भीख मांग रहे हैं।
फिलिप

0

ऊपर के साथ एक टिप्पणी में डिजाइन किए मुद्दों के दस्तावेज जोड़े। लघु कहानी, ओरेकल में, आपको मैन्युअल रूप से परिणामों को सीमित करने की आवश्यकता होती है जब आपके पास बड़े कॉलम और / या एक ही कॉलम नाम वाली टेबल होती हैं (और आप उन्हें स्पष्ट रूप से टाइप नहीं करना चाहते हैं और उन सभी का नाम बदल सकते हैं)। आसान समाधान यह है कि अपने ब्रेकपॉइंट का पता लगाएं और अपनी क्वेरी में इसे सीमित करें। या यदि आप परस्पर विरोधी स्तंभ नाम बाधा नहीं रखते हैं, तो आप इसे आंतरिक क्वेरी में भी कर सकते हैं। उदाहरण के लिए

WHERE m_api_log.created_date BETWEEN TO_DATE('10/23/2015 05:00', 'MM/DD/YYYY HH24:MI') 
                                 AND TO_DATE('10/30/2015 23:59', 'MM/DD/YYYY HH24:MI')  

काफी हद तक परिणामों में कटौती करेगा। तब आप पंक्ति को सीमित कर सकते हैं या पंक्तियों को सीमित करने के लिए बाहरी क्वेरी भी कर सकते हैं।

इसके अलावा, मुझे लगता है कि TOAD में पंक्तियों को सीमित करने की सुविधा है; लेकिन, यकीन नहीं है कि Oracle पर वास्तविक क्वेरी के भीतर सीमित है। निश्चित नहीं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.