2009-06-02 9 views
5

मैं निम्नलिखितक्या बाध्य चर के साथ ग्रुप BY का उपयोग करना संभव है?

select max(col1), f(:1, col2) from t group by f(:1, col2) 

जहां :1 एक बाँध चर रहा है की तरह एक प्रश्न जारी करने के लिए चाहते हैं। PreparedStatement का उपयोग करना, अगर मैं कहूँ

connection.prepareStatement 
    ("select max(col1), f(?, col2) from t group by f(?, col2)") 

मैं डीबीएमएस शिकायत की कि f(?, col2) अभिव्यक्ति द्वारा एक ग्रुप नहीं है से कोई त्रुटि मिलती है।

कोई सामान्य रूप से जेडीबीसी में इसे कैसे हल करता है?

+0

आप वास्तव में क्या बांधना चाहते हैं? हमें बस अपना स्निपेट न करें, न सिर्फ एक स्निपेट। आप 'YYYY' जैसे मान को बाध्य कर सकते हैं लेकिन कॉलम नाम नहीं। – tuinstoel

+1

अपडेट: अब मुझे लगता है कि क्या गलत है। डीबीएमएस यह स्वीकार नहीं कर रहा है कि ग्रुप BY में अभिव्यक्ति SELECT सूची में एक ही अभिव्यक्ति है। यह उनको दो अलग-अलग अभिव्यक्तियों के रूप में देख रहा है। एक नामित बाइंड वैरिएबल का उपयोग उस समस्या से बचाता है, क्योंकि केवल एक मान है। – spencer7593

उत्तर

8

मैं कथन को दोबारा लिखने का सुझाव देता हूं ताकि केवल एक बाध्य तर्क हो। यह दृष्टिकोण बदसूरत की तरह है, लेकिन परिणाम सेट देता है:

select max(col1) 
    , f_col2 
    from (
     select col1 
       , f(? ,col2) as f_col2 
      from t 
     ) 
group 
    by f_col2 

यह फिर से लिखित बयान केवल एक ही बाँध तर्क के लिए एक संदर्भ है, इसलिए अब डीबीएमएस ग्रुप में भाव खंड और द्वारा देखता है चयन सूची समान हैं।

HTH

[संपादित करें]

(मैं एक खूबसूरत तरीका वहाँ थे इच्छा, इस कारण है कि मैं नामित बाँध तर्क दृष्टिकोण है कि ओरेकल उपयोग करता है। पर्ल DBI ड्राइवर के साथ पसंद करते हैं, स्थितीय तर्क में बदल दिए जाते है वास्तव में ओरेकल को भेजे गए बयान में तर्कों का नाम दिया गया।)

मुझे पहली बार समस्या नहीं दिखाई दे रही थी, मुझे मूल प्रश्न नहीं समझा। (जाहिर है, कई अन्य लोगों ने भी इसे याद किया।) लेकिन कुछ परीक्षण मामलों के बाद, यह मेरे सामने आया कि समस्या क्या थी, सवाल क्या काम कर रहा था।

मुझे देखने दो कि क्या मैं समस्या बता सकता हूं: दो अलग-अलग (स्थितित्मक) बाध्य तर्कों को कैसे प्राप्त किया जाए (डीबीएमएस द्वारा) जैसे कि यह समान (नामित) बाइंड तर्क के दो संदर्भ थे।

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

इस बिंदु पर संक्षिप्त जवाब यह है कि मुझे स्टंप हो गया है। मेरे पास सुझाव है (जो मूल प्रश्न का वास्तविक उत्तर नहीं हो सकता है) क्वेरी को पुन: स्थापित करना है।

[/ संपादित करें]

मैं अगर इस दृष्टिकोण काम नहीं करता है अधिक जानकारी प्रदान कर सकते हैं, या आप कुछ अन्य समस्या यह पता लगाना है। या यदि प्रदर्शन के साथ कोई समस्या है (मैं फिर से लिखित क्वेरी के लिए एक अलग योजना चुनने वाला ऑप्टिमाइज़र देख सकता हूं, भले ही यह निर्दिष्ट परिणाम सेट देता है। आगे के परीक्षण के लिए, हमें वास्तव में यह जानने की आवश्यकता होगी कि डीबीएमएस, क्या ड्राइवर, सांख्यिकी, आदि)

संपादित (आठ और एक आधा साल बाद)

एक प्रश्न पुनर्लेखन पर एक और प्रयास। दोबारा, एकमात्र समाधान जो मैं आया हूं वह एक बाध्य प्लेसहोल्डर के साथ एक प्रश्न है। इस बार, हम इसे एक इनलाइन व्यू में चिपकते हैं जो एक पंक्ति को लौटाता है, और उसमें शामिल होता है। मैं देख सकता हूं कि यह क्या कर रहा है; मुझे यकीन नहीं है कि ओरेकल ऑप्टिमाइज़र इसे कैसे देखेगा। हम एक स्पष्ट रूपांतरण करना चाहते हैं (या आवश्यकता) उदा। TO_NUMBER(?) AS param, TO_DATE(?,'...') AS param, TO_CHAR(?) AS param, बाँध पैरामीटर के डेटाप्रकार, और डेटाप्रकार हम देखने से के रूप में वापस किया जाना चाहते हैं पर निर्भर करता है।)

यह कैसे मैं MySQL में यह करना होगा। मेरे उत्तर में मूल क्वेरी इनलाइन व्यू के अंदर शामिल ऑपरेशन करता है (MySQL व्युत्पन्न तालिका)। और हम एक हूजज व्युत्पन्न तालिका को भौतिक बनाने से बचना चाहते हैं अगर हम इससे बच सकते हैं। फिर फिर, MySQL शायद मूल क्वेरी स्लाइड को तब तक दे देगा जब तक sql_mode में ONLY_FULL_GROUP_BY शामिल नहीं है। MySQL भी हमें JDBC ड्राइवर में एक ही नाम दिया बाँध मापदंडों पुन: उपयोग, और तुल्यता बनाए रखने के लिए छोड़ FROM DUAL)

SELECT MAX(t.col1) 
     , f(v.param ,t.col2) 
    FROM t 
    CROSS 
    JOIN (SELECT ? AS param FROM DUAL) v 
    GROUP 
     BY f(v.param ,t.col2) 

MadusankaD से जवाब के मुताबिक, पिछले आठ वर्षों के भीतर, ओरेकल जोड़ा गया है समर्थन करते हैं। (मैं परीक्षण किया है नहीं है, लेकिन यह है कि अगर अब काम करता है, तो महान।)

0

क्या आपने नामित बाइंड चर के बजाए ? का उपयोग करने का प्रयास किया था? साथ ही, आप किस ड्राइवर का उपयोग कर रहे हैं? मैं पतली ड्राइवर का उपयोग कर इस तुच्छ उदाहरण की कोशिश की, और यह ठीक काम करने के लिए लग रहा था:

PreparedStatement ps = con.prepareStatement("SELECT COUNT(*), TO_CHAR(SYSDATE, ?) FROM DUAL GROUP BY TO_CHAR(SYSDATE, ?)"); 
ps.setString(1, "YYYY"); 
ps.setString(2, "YYYY"); 
ps.executeQuery(); 
0

दूसरे मामले में, वहाँ वास्तव में दो चर रहे हैं - आप उन दोनों को एक ही मूल्य के साथ भेजने की आवश्यकता होगी।

+0

@ कैड: एक ही मूल्य पर दोनों चर सेट करना पर्याप्त नहीं है, डीबीएमएस दो अलग-अलग बाध्य तर्क देख रहा है। डीबीएमएस चयन और ग्रुप बाय में विभिन्न अभिव्यक्ति देख रहा है। – spencer7593

+0

मुझे चिंता थी कि यह मामला हो सकता है। मैं हमेशा संग्रहीत प्रोसेस का उपयोग करता हूं। –

1

भले ही आप JDBC ड्राइवर के माध्यम से एक प्रश्न जारी किए गए हैं (PreparedStatement का प्रयोग करके) इस तरह:

select max(col1), f(:1, col2) from t group by f(:1, col2) 

पिछले JDBC ड्राइवर पर डाटाबेस पर पार्सिंग से पहले इन्हें नीचे की क्वेरी की तरह बदल देता है, भले ही आपने दोनों जगहों पर एक ही बाध्यकारी चर नाम का उपयोग किया हो।

select max(col1), f(*:1*, col2) from t group by f(*:2*, col2) 

लेकिन ऑरैकल में इसे क्लॉज द्वारा मान्य समूह के रूप में पहचाना नहीं जाएगा। और सामान्य जेडीबीसी ड्राइवर नामित बाध्य चर का समर्थन नहीं करता है।

इसके लिए आप अपने कनेक्शन के लिए OraclePreparedStatement कक्षा का उपयोग कर सकते हैं। इसका मतलब है कि यह ओरेकल जेडीबीसी है। फिर आप नामित बाइंड चर का उपयोग कर सकते हैं। यह आपकी समस्या का समाधान करेगा।

ओरेकल डेटाबेस 10 जी जेडीबीसी ड्राइवरों से शुरू, नाम से बाध्य setXXXAtName विधियों का उपयोग करके समर्थित है।

http://docs.oracle.com/cd/E24693_01/java.11203/e16548/apxref.htm#autoId20

+0

अच्छा। यह एक सुधार है (एक * सिंगल * नामित बाइंड पैरामीटर सेट करने के लिए 'setXXXAtName' विधि, और उसी बाइंड प्लेसहोल्डर को उसी कथन में * एकाधिक * स्थानों का संदर्भ दिया गया है, और ओरेकल ऑप्टिमाइज़र यह मानते हुए कि प्लेसहोल्डर के साथ एक अभिव्यक्ति समान है, इसलिए ग्रुप बाय क्लॉज और चयन सूची में एक ही अभिव्यक्ति का उपयोग किया जा सकता है। यह वेनिला जेडीबीसी पर कार्यक्षमता में भारी सुधार है। – spencer7593

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