2012-04-10 11 views
5

गूंगा प्रश्न समय में शामिल होने वाले खंड को प्रभावित करते हैं। ओरेकल 10 जी।जहां

क्या यह एक धारा के लिए शामिल होने के लिए संभव है?

मैं के रूप में एक प्रश्न मिल गया है:

select * from 
(select product, product_name from products p 
join product_serial ps on product.id = ps.id 
join product_data pd on pd.product_value = to_number(p.product_value)) product_result 
where product_name like '%prototype%'; 

जाहिर है यह एक काल्पनिक उदाहरण है। तालिका संरचना को दिखाने की कोई वास्तविक आवश्यकता नहीं है क्योंकि यह सभी काल्पनिक है। दुर्भाग्यवश, मैं वास्तविक तालिका संरचना या क्वेरी नहीं दिखा सकता। इस मामले में, p.product_value एक VARCHAR2 फ़ील्ड है जिसमें कुछ पंक्तियों में पाठ के बजाय इसके अंदर एक आईडी संग्रहीत होती है। (हाँ, खराब डिज़ाइन - लेकिन कुछ जो मैंने विरासत में लिया है और बदलने में असमर्थ हूं)

समस्या शामिल है। अगर मैं कहां से निकलता हूं, क्वेरी काम करता है और पंक्तियां वापस आती हैं। हालांकि, अगर मैं कहां जोड़ता हूं, तो मुझे pd.product_value = to_number (p.product_value) स्थिति में "अमान्य संख्या" त्रुटि मिलती है।

जाहिर है, पंक्तियों में शामिल होने पर "अमान्य संख्या" त्रुटि तब होती है जिसमें p.product_value फ़ील्ड में गैर-अंक होते हैं। हालांकि, मेरा सवाल यह है कि उन पंक्तियों का चयन कैसे किया जा रहा है? अगर शामिल बाहरी के बिना सफल हो जाता है, तो बाहरी नहीं होना चाहिए जहां क्लॉज सिर्फ शामिल होने के परिणाम से पंक्तियों का चयन करें? ऐसा लगता है कि क्या हो रहा है, जहां एक पंक्ति में शामिल होने के बावजूद, खंड किस पंक्ति में शामिल हो रहा है, इस पर प्रभाव डाल रहा है।

क्या मेरा प्रश्न समझ में आता है?

+0

आप इसे थोड़ा slack 'to_char (pd.product_value) = p.product_value' दे सकते हैं। – briantyler

उत्तर

1

संक्षिप्त उत्तर: हाँ।

लंबा उत्तर: क्वेरी इंजन आपकी क्वेरी को फिर से लिखने के लिए स्वतंत्र है, हालांकि यह चाहता है, जब तक यह वही परिणाम देता है। सबसे अधिक क्वेरी पूछने के उद्देश्य के लिए उपयोग करने के लिए सभी क्वेरी इसका उपयोग करने के लिए उपलब्ध है।

इस मामले में, मुझे लगता है कि एक इंडेक्स है जो आप जो चाहते हैं उसे कवर करता है, लेकिन इसमें उत्पाद का नाम शामिल नहीं होता है, जब आप उस खंड में जोड़ते हैं, तो इंडेक्स का उपयोग नहीं किया जाता है और इसके बजाए एक स्कैन है जहां एक ही समय में दोनों स्थितियों का परीक्षण किया जाता है, इस प्रकार आपकी त्रुटि।

जो आपकी जॉइन स्थिति में वास्तव में एक त्रुटि है, आपको तब तक उपयोग नहीं करना चाहिए जब तक आप सुनिश्चित न हों कि यह एक संख्या है।

0

मुझे लगता है कि आपका to_number(p.product_value) केवल वैध product_name के साथ पंक्तियों के लिए लागू होता है।

क्या होता है कि आपका join आपके where खंड से पहले लागू होता है जिसके परिणामस्वरूप to_number फ़ंक्शन की विफलता होती है।

select * from 
(select product, product_name from products p 
join product_serial ps on product.id = ps.id 
join product_data pd on product_name like '%prototype%' AND 
    pd.product_value = to_number(p.product_value)); 
+0

यह मदद कर सकता है या नहीं भी हो सकता है - पहले 'to_number' का मूल्यांकन करने का प्रयास करने से ओरेकल को रोकना कुछ भी नहीं है। –

2

यह योजना है कि उत्पन्न प्रभावित करता है:

आप क्या करने की जरूरत है इस तरह अपने खंड product_name like '%prototype%'JOIN एक के रूप में शामिल है।

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

एक संस्करण में, सह-आकस्मिक रूप से उत्पन्न योजना का अर्थ है कि 'बुरी' पंक्तियों को कभी संसाधित नहीं किया जाता है; क्योंकि पूर्ववर्ती जोड़ों ने परिणाम को फ़िल्टर करने के लिए फ़िल्टर किया है कि वे कभी भी शामिल नहीं हुए हैं।

WHERE खंड का परिचय यह है कि ओआरएसीएलई का मानना ​​है कि शामिल होने का एक अलग क्रम बेहतर है (क्योंकि उत्पाद के नाम से फ़िल्टर करने के लिए एक निश्चित इंडेक्स की आवश्यकता होती है, या क्योंकि यह डेटा को बहुत कम करता है, आदि)।

इस नए आदेश का अर्थ है कि 'खराब' पंक्तियों को उन फ़िल्टर करने से पहले संसाधित किया जाता है जो उन्हें फ़िल्टर करते हैं।


मैं इसे क्वेरी करने से पहले डेटा को साफ करने का प्रयास करेंगे। संभवतः एक व्युत्पन्न कॉलम बनाकर जहां मान पहले से ही किसी संख्या में डाला गया है, या ऐसा करने के लिए संभव नहीं है तो NULL के रूप में छोड़ा गया है।

आप अपने प्रश्नों से भूरे रंग की विभिन्न योजनाओं को देखने के लिए एक्सप्लाइन प्लान का भी उपयोग कर सकते हैं।

0

अधिक पृष्ठभूमि (और वास्तव में अच्छा पढ़ने के लिए), मैं जोनाथन गेनिक के Subquery Madness पढ़ने का सुझाव दूंगा।

असल में, समस्या यह है कि ओरेकल किसी भी क्रम में भविष्यवाणियों का मूल्यांकन करने के लिए स्वतंत्र है। इसलिए product_name आपके सबक्वायरी में भविष्यवाणी करने के लिए (या धक्का नहीं) मुक्त है। किसी भी क्रम में शामिल स्थितियों का मूल्यांकन करना स्वतंत्र है। तो यदि ओरेकल एक क्वेरी प्लान चुनने के लिए होता है जहां यह to_number लागू करने से पहले गैर-न्यूमेरिक product_value पंक्तियों को फ़िल्टर करता है, तो क्वेरी सफल होगी। यदि गैर-न्यूमेरिक product_value पंक्तियों को फ़िल्टर करने से पहले यह एक योजना चुनने के लिए to_number लागू होता है, तो आपको एक त्रुटि मिल जाएगी। बेशक, यह भी संभव है कि यह पहली एन पंक्तियों को सफलतापूर्वक वापस कर देगी और फिर जब आप पंक्ति एन + 1 लाने की कोशिश करते हैं तो आपको एक त्रुटि मिलेगी क्योंकि पंक्ति एन + 1 पहली बार है कि यह to_number भविष्यवाणी लागू करने का प्रयास कर रहा है एक गैर-संख्यात्मक डेटा के लिए।

डेटा मॉडल को ठीक करने के अलावा, आप संभावित रूप से ओरेकल को भविष्यवाणी करने के लिए मजबूर करने के लिए क्वेरी में कुछ संकेत डाल सकते हैं जो यह सुनिश्चित करता है कि to_number भविष्यवाणी से पहले सभी गैर-संख्यात्मक डेटा फ़िल्टर हो जाएं। लेकिन आम तौर पर, यह एक प्रश्न को पूरी तरह से संकेत देने के लिए थोड़ा चुनौतीपूर्ण है जो अनुकूलक को हमेशा "उचित" क्रम में चीजों का मूल्यांकन करने के लिए मजबूर करेगा।

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