2012-02-17 10 views
5

अरे दोस्तों मैं इस पर अपने सिर खरोंच कर रहा हूं, मुझे उम्मीद है कि कोई इसे के लिए समझा सकता है। ईमानदारी से मैं थोड़ा डर रहा हूं कि यह मुझे बाद में गधे में काट सकता है ....MYSQL जॉइन अप्रत्याशित (लेकिन सुखद) परिणाम देता है?

तो, मेरे पास तीन टेबल हैं जो मैं वर्तमान में खींच रहा हूं। reports, berries और melons। मैंने अपनी क्वेरी इस तरह स्थापित की है, और यह मुझे वही बनाता है जो मैं चाहता हूं।

SELECT 
    rpt.*, 
    ber.shipper, ber.po, ber.commodity, ber.label 

FROM reports rpt 

LEFT JOIN berries ber ON rpt.inspection_number = ber.report_key 
LEFT JOIN melons mel ON rpt.inspection_number = mel.report_key 

WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 

मैं अपने प्रत्याशित प्रतिफल जो

key | role | region | inspection_type | inspection_number | shipper | po | commodity  | label 
3 | NULL | Seattle | melons   | 5555    | Shipper1 | PO2 | Commodity2 | Label2 
2 | NULL | Seattle | berries   | 1023    | Shipper1 | PO1 | Commodity1 | Label1 

है, हालांकि मैं अपने बयान से LEFT JOIN melons mel ON rpt.inspection_number = mel.report_key को दूर मैं बिल्कुल वही चीज़ मिल हो रही है .... मैं कभी नहीं उल्लेख किया melons ??

अगर मैं संशोधित और जामुन

SELECT 
    rpt.*, 
    ber.shipper, ber.po, ber.commodity, ber.label 

FROM reports rpt 

JOIN berries ber ON rpt.inspection_number = ber.report_key 

WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 

के लिए बजाय JOIN का उपयोग यह पैदा करता है मेरी अपेक्षा यह होना चाहिए!

key | role | region | inspection_type | inspection_number | shipper | po | commodity  | label 
2 | NULL | Seattle | berries   | 1023    | Shipper1 | PO1 | Commodity1 | Label1 

लेकिन अब की तरह मेरे एसक्यूएल बयान को संशोधित करने की कोशिश कर रहा ....

SELECT 
    rpt.*, 
    ber.shipper, ber.po, ber.commodity, ber.label 
    mel.shipper, mel.po, mel.commodity, mel.label 

FROM reports rpt 

JOIN berries ber ON rpt.inspection_number = ber.report_key 
JOIN melons mel ON rpt.inspection_number = mel.report_key 

WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 

जाल मुझे ....

MySQL returned an empty result set (i.e. zero rows). (Query took 0.0011 sec) मुझे बड़ा बीच की उँगली देता है। क्या बकवास है? क्या कोई बता सकता है कि मैं स्पष्ट रूप से गलत कर रहा हूं, और इसे कैसे ठीक किया जाए?

+1

क्या यह बदले में उसी तालिका में जामुन और खरबूजे होने का अर्थ होगा? –

+1

मेरी इच्छा है कि मैं कर सकता हूं, लेकिन वास्तव में हमारे पास लगभग 12 फल प्रकार हैं, जिनमें से सभी के अपने अलग-अलग क्षेत्र हैं। उन्हें सहारा देने की कोशिश कर रहे हैं, और उनका सहारा लेना एक दुःस्वप्न होगा .... अच्छा सवाल हालांकि! – ehime

+0

मेरा मानना ​​है कि आपको 'बाएं जॉइन' के साथ 'मेल' के साथ और बिना एक ही परिणाम मिलेंगे, लेकिन मुझे आपके परिणामों पर विश्वास नहीं है। प्रत्येक तरबूज पंक्ति के लिए 'शिपर', 'पीओ', और अन्य 'बियर' कॉलम न्यूल होंगे। –

उत्तर

5

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

SELECT 
    rpt.*, 
    COALESCE(ber.shipper, mel.shipper) AS shipper, 
    COALESCE(ber.po, mel.po) AS po, 
    COALESCE(ber.commodity, mel.commodity) AS commodity, 
    COALESCE(ber.label, mel.label) AS label 
FROM reports rpt 
LEFT JOIN berries ber ON rpt.inspection_number = ber.report_key 
LEFT JOIN melons mel ON rpt.inspection_number = mel.report_key 
WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 

इस क्वेरी का कहना है, मुझे पंक्तियों जहां एक जामुन या खरबूजे में शामिल होने के वहाँ देते हैं, लेकिन के लिए वे कॉलम सामान्य हैं, जो भी एक मौजूद है मुझे दे दो। हम किसी विशेष कारण के लिए पहले बियर ले रहे हैं।

मानते हैं कि इन दो तालिकाओं परस्पर अनन्य हैं, मुझे लगता है कि यह वही है जो आप चाहते हैं।

संपादित: क्या @MarcusAdams पर इमारत से नीचे बताते हैं, यह एक UNION उपयोग करने के लिए अगर वहाँ फल टेबल के एक अप्रिय संख्या में हैं फिर से लिखा जा सकता है:

SELECT report_key, shipper, po, commodity, label FROM berries 
UNION 
SELECT report_key, shipper, po, commodity, label FROM melons 
UNION 
SELECT report_key, shipper, po, commodity, label FROM ... 
... 

इस क्वेरी आप कुछ आप काम दे देंगे बाद में एक सबक्वायरी (या देखें) के रूप में उपयोग कर सकते हैं।आप कर सकते हैं तो जैसे भी कड़ी मेहनत से कोड एक मूल नाम:

SELECT report_key, shipper, po, commodity, label, 'berries' AS type FROM berries 
UNION 
SELECT report_key, shipper, po, commodity, label, 'melons' FROM melons 
UNION 
SELECT report_key, shipper, po, commodity, label, '...' FROM ... 
... 
फिर

आपकी मूल क्वेरी में इस का उपयोग करने के लिए, आप इसे इतना तरह एम्बेड होगा:

SELECT * 
FROM reports rpt, 
JOIN (SELECT report_key, shipper, po, commodity, label, 'berries' AS type FROM berries 
     UNION 
     SELECT report_key, shipper, po, commodity, label, 'melons' FROM melons 
     UNION 
     SELECT report_key, shipper, po, commodity, label, '...' FROM ... 
     ...) fruits ON rpt.inspection_number = fruits.report_key 
WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 
+0

ऐसा लगता है जैसे यह काम करता है, लेकिन मैंने देखा कि मेरा 'rpt.status' मेरा' mel.status' और 'ber.status' ओवरराइट कर रहा है? मुझे लगता है कि मुझे कुछ और चाहिए जैसे 'mel.status> 2 और ber.status> 2'? वह आवाज सही है, या यहां तक ​​कि समझ में आता है? – ehime

+0

आप 'mel.status' या' ber.status' का चयन नहीं कर रहे हैं - आपको इसे उपरोक्त अन्य चार कॉलम की तरह क्वेरी में जोड़ना होगा। –

+0

तो 'COALESCE (ber.status, mel.status) AS fruitstatus, COALESCE (rpt.status, rpt.status) AS रिपोर्टस्टैटस' और फिर 'रिपोर्ट रिपोर्ट =' 1 'या रिपोर्टस्टैटस =' 0 'और fruitstatus =' 1 ' या fruitstatus = '0'' सही? – ehime

0

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

SELECT 
    rpt.*, 
    ber.shipper, ber.po, ber.commodity, ber.label 

इसके बाद, मैं एक LEFT JOIN के बीच मतभेद, एक INNER JOIN, और सिर्फ एक JOIN साथ भी परिचित नहीं हूँ, इसलिए मुझे लगता है कि सवाल का जवाब नहीं कर सकते हैं। हालांकि, MySQL के साथ अपने अनुभव से, जॉइन के बजाय अंतिम क्वेरी को अंतिम जॉइन में बदलने का प्रयास करें और देखें कि क्या यह काम करता है। विभिन्न प्रकार के जॉइन के बीच मतभेदों के संबंध में MySQL साइट पर documentation है।

मुझे बताएं कि क्या आप अभी भी मुद्दों में चल रहे हैं और मैं आपकी सहायता करने की कोशिश करूंगा। उम्मीद है कि मैंने कम से कम कुछ प्रश्नों का उत्तर दिया है।

+1

किसी भी उपसर्ग _is_ 'INNER JOIN' के बिना 'जॉइन'। –

3

नीचे दी गई क्वेरी कि डैनियल लियोन प्रदान करता है, लेकिन मैं इसे थोड़ा सा चर्चा करना चाहता हूं, और सख्ती से अकादमिक उद्देश्यों के लिए, एक और समाधान प्रदान करता हूं, जो अधिक अनुकूलित होने की संभावना है।

SELECT 
    rpt.*, 
    COALESCE(ber.shipper, mel.shipper) AS shipper, 
    COALESCE(ber.po, mel.po) AS po, 
    COALESCE(ber.commodity, mel.commodity) AS commodity, 
    COALESCE(ber.label, mel.label) AS label 
FROM reports rpt 
LEFT JOIN berries ber ON rpt.inspection_number = ber.report_key 
LEFT JOIN melons mel ON rpt.inspection_number = mel.report_key 
WHERE rpt.status='1' OR rpt.status='0' 
ORDER BY rpt.inspection_number DESC 

इस क्वेरी अच्छा काम करता है, और केवल दो फल के लिए, यह काफी अनुरूप होता है:

यहाँ डैनियल क्वेरी है। अभी भी रिपोर्ट पारस्परिक रूप से अनन्य हैं, इसलिए क्वेरी आवश्यकतानुसार अतिरिक्त जुड़ाव का प्रयास कर रही है। उदाहरण के लिए, यदि एक रिपोर्ट रिकॉर्ड पहले से ही बेरी रिकॉर्ड में शामिल हो चुका है, तो हम जानते हैं कि यह एक तरबूज रिकॉर्ड में शामिल नहीं होने वाला है, लेकिन MySQL उसे नहीं जानता है। इसके बजाय, MySQL तरबूज तालिका में शामिल होने का प्रयास करने के लिए एक और लुकअप करेगा, भले ही एक संबंधित रिकॉर्ड नहीं मिलेगा।

केवल दो जुड़ने के साथ, शामिल प्रयासों में से आधे बर्बाद हो जाते हैं। हालांकि, तीन फलों के साथ, दो-तिहाई जुड़ने के प्रयास बर्बाद हो जाते हैं, चार फलों के साथ, तीन-चौथाई शामिल प्रयासों को बर्बाद कर दिया जाता है, और इसी तरह।

अतिरिक्त प्रयास में शामिल होने से बचने के लिए, हम इस तरह की मिलती है क्रम को उल्टा कर सकते हैं:

(SELECT rpt.*, ber.shipper, ber.po, ber.commondity, ber.label 
FROM berries ber 
JOIN reports rpt 
    ON rpt.inspection_number = ber.report_key 
WHERE rpt.status = '1' OR rpt.status = '0') 
UNION ALL 
(SELECT rpt.*, mel.shipper, mel.po, mel.commondity, mel.label 
FROM melons mel 
JOIN reports rpt 
    ON rpt.inspection_number = mel.report_key 
WHERE rpt.status = '1' OR rpt.status = '0') 
ORDER BY inspection_number DESC 

यहाँ, हम (फल) के साथ दूसरी दिशा से शुरू कर रहे हैं, और वापस करने के लिए शामिल होने के रिपोर्ट। यह हमें प्रति रिपोर्ट में केवल एक शामिल करने की अनुमति देता है।

सूचना है कि अब हम INNER JOIN बजाय LEFT JOIN का उपयोग कर रहे प्रत्येक फल के लिए, और हम एक बड़ा परिणाम सेट में प्रत्येक फल के लिए परिणाम शामिल होने के लिए UNION ALL उपयोग कर रहे हैं।

आगे अनुकूलन के लिए, कभी-कभी MySQL 1 और 0 जैसे दो स्थिरांक को एक सीमा के रूप में नहीं पहचानता है, खासकर अगर यह एक पूर्णांक क्षेत्र नहीं है। रेंज लुकअप दो अलग-अलग लुकअप से तेज़ हैं, इसलिए MySQL को संकेत देने के लिए कि 1 और 0 का rpt.status एक श्रेणी है, OR के बजाय BETWEEN का उपयोग करें, मान लें कि आपके पास (rpt.inspection_number, rpt.status) का कवर इंडेक्स है।

+0

यूनियनों पर जाने के लिए http://chat.stackoverflow.com/rooms/7868/pleasant-sql-results में मुझे शामिल होने का मन? – ehime

+0

क्षमा करें, मुझे एक बैठक में कदम उठाना पड़ा। अब, मैं सप्ताहांत के लिए बंद हूँ। –

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