मेरे पास निम्न क्वेरी है जो 4 परिणाम लौटा रही है जब तालिका FI_CurrentReceiptData में केवल 2 पंक्तियां होती हैं। अतिरिक्त पंक्तियाँ सटीक डुप्लिकेट हैं। मैं ठीक करने के लिए DISTINCT का उपयोग कर सकता हूं, लेकिन मेरी समझ यह है कि यह खराब अभ्यास है और मैं त्रुटि को खोजने और ठीक करने के लिए बेहतर करूंगा (क्या यह सही है?)

यह प्रश्न परिणामों को दोगुना क्यों कर रहा है?

सभी चर एक संग्रहीत प्रक्रिया में कहीं और घोषित किए जाते हैं और यह क्वेरी आवश्यक फ़ील्ड लौटाती है।

SELECT ( (Select Max(ReceiptNumber)
          from   Avanti_InventoryReceipts) + CR.Seq ),
       CR.ItemNumber,
       Convert(char(8), GETDATE(), 112),
       PONum,
       'FL-INV',
       PH.POVendor,
       0,
       0,
       'O',
       CR.QtyOrdered,
       QtyReceivedToday,
       QtyReceivedToday,
       Case @closePO
         When 'N' Then Case
                         When ( QtyOrdered - QtyReceivedToday ) < 0 Then 0
                         Else ( QtyOrdered - QtyReceivedToday )
                       End
         When 'Y' Then 0
         Else 0
       End,
       PD.TransCost * QtyReceivedToday,
       IH.PriceWholeSale,
       IH.CostLast,
       QtyReceivedToday,
       0,
       '',
       PODetailDescription /* , .... More columns...*/

FROM   FI_CurrentReceiptData CR
       LEFT JOIN Avanti_PODetails PD
         ON CR.PONum = PD.PONumber
       LEFT JOIN Avanti_POHeader PH
         ON CR.PONum = PH.PONumber
       LEFT JOIN Avanti_InventoryHeader IH
         ON CR.ItemNumber = IH.ItemNumber  

नया जहां क्लॉज समाधान:

FROM FI_CurrentReceiptData CR
inner JOIN Avanti_PODetails PD ON CR.PONum = PD.PONumber AND CR.ItemNumber = PD.TransItem AND CR.QtyOrdered = PD.TransQty
left JOIN Avanti_POHeader PH ON PD.PONumber = PH.PONumber
left JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
0
MAW74656 6 सितंबर 2011, 19:00
स्मिथ-सुधार के लिए धन्यवाद। मैं ऐसा करने में धीमा हूं।
 – 
MAW74656
6 सितंबर 2011, 19:04
3
मैंने इसे यहां dpriver.com/pp/sqlformat.htm के माध्यम से चकमा दिया।
 – 
Martin Smith
6 सितंबर 2011, 19:05
स्मिथ-मैं हर समय इसका इस्तेमाल करता हूं, लेकिन मुझे नहीं पता था कि एसओ स्वरूपण का सम्मान करेगा।
 – 
MAW74656
6 सितंबर 2011, 19:08
मुझे लगता है कि इसमें शामिल सभी तालिकाओं में 1 से कई संबंध हैं? क्या आप सुनिश्चित हैं कि पंक्तियाँ सही डुप्ली हैं? यदि आप परिणाम में शामिल सभी 4 तालिकाओं का पीके जोड़ते हैं तो क्या निश्चित रूप से दोहराना है?
 – 
Martin Smith
6 सितंबर 2011, 19:13
स्मिथ-हां, प्राथमिक कुंजी जोड़ना सही डुप्लिकेट की पुष्टि करता है। सीआर में 2 रिकॉर्ड हैं, पीडी के 2 रिकॉर्ड हैं, आईएच और पीएच दोनों के पास 1 संबंधित रिकॉर्ड है।
 – 
MAW74656
6 सितंबर 2011, 19:17

3 जवाब

सबसे बढ़िया उत्तर

सम्मिलित तालिकाओं में से एक में एक से अधिक मेल खाने वाली पंक्तियाँ हैं। मैं निश्चित रूप से नहीं कह सकता कि कौन सा है, लेकिन अगर मैं तुम होते तो मैं Avanti_PODetails तालिका को देखना शुरू कर देता। क्या इसके पास दो रसीदों में से किसी एक के लिए एक से अधिक मिलान रिकॉर्ड हैं?

0
Klas Lindbäck 6 सितंबर 2011, 19:14
और अनुवर्ती प्रश्न यह है: क्या उनके पास अलग-अलग PONumbers हैं? (मैं ऊपर की टिप्पणियों से देखता हूं कि आपको पहले ही डुप्लिकेट मिल गया है)
 – 
Klas Lindbäck
6 सितंबर 2011, 19:32
-हां, PONumbers को डुप्लीकेट माना जाता है। मुझे यकीन नहीं है कि आपका क्या मतलब है, क्या आप समस्या देखते हैं?
 – 
MAW74656
6 सितंबर 2011, 19:43
अगर आपके पास डुप्लीकेट PONumbers हैं, तो आपको डुप्लीकेट आउटपुट मिलेगा। एकल आउटपुट प्राप्त करने के लिए आपको उन क्षेत्रों के संयोजन में शामिल होना होगा जो एक अद्वितीय रिकॉर्ड से मेल खाते हों।
 – 
Klas Lindbäck
7 सितंबर 2011, 10:28
लिंडबैक - मैं अब देखता हूँ! डुप्लीकेट से छुटकारा पाने के लिए मुझे वास्तव में पीओ विवरण और CurrentReceiptData के बीच 3 क्षेत्रों में शामिल होना पड़ा। मुझे DISTINCT से बचने की कोशिश करने का अधिकार है, हां?
 – 
MAW74656
7 सितंबर 2011, 18:55
हां, DISTINCT से बचना एक अच्छा नियम है। लेकिन याद रखें, ऐसी परिस्थितियाँ होती हैं जहाँ आपको इसकी आवश्यकता होती है। नियम इसलिए नहीं है क्योंकि DISTINCT खराब है, नियम इसलिए है क्योंकि अक्सर लोग DISTINCT का उपयोग इस तथ्य को कवर करने के लिए करते हैं कि उनकी शामिल होने की स्थिति अपर्याप्त है।
 – 
Klas Lindbäck
8 सितंबर 2011, 11:23

आमतौर पर जब आप लेफ्ट जॉइन करते हैं, तो आपको 'लेफ्ट' टेबल से जुड़ते रहना होता है - यह एक नियम नहीं है बल्कि यह अच्छा अभ्यास है ताकि आप जुड़ने से न चूकें। आपके लेफ्ट जॉइन की स्ट्रिंग में, इसमें 4 टेबल शामिल हैं, और आप तीनों में से केवल पहले वाले में शामिल हुए हैं:


FROM   FI_CurrentReceiptData CR 
       LEFT JOIN Avanti_PODetails PD 
         ON CR.PONum = PD.PONumber 
       LEFT JOIN Avanti_POHeader PH 
         ON CR.PONum = PH.PONumber 
       LEFT JOIN Avanti_InventoryHeader IH 
         ON CR.ItemNumber = IH.ItemNumber   


आप पीडी से आईएच से पीएच में शामिल नहीं हो रहे हैं, लेकिन मूल रूप से सीआर तालिका में तीनों में शामिल होना छोड़ दिया है - इसलिए अनिवार्य रूप से यह पीडी और पीएच और आईएच के बीच एक क्रॉस जॉइन कर रहा है (जो भी फ़ील्ड वे मेल खाते हैं उसके आधार पर)। मुझे लगता है कि POheader और POdetails में कुछ फ़ील्ड हैं जिन पर वे मेल खाते हैं .... और मुझे लगता है कि यह तालिकाओं के बीच कई संबंधों में से एक है? (नामों के आधार पर)। तो वहां कुछ प्रतिबंध लगाने की जरूरत है ...

संपादित करें:

तो क्या आप कोशिश कर सकते हैं, (क्षेत्र संबंधों के आधार पर)


FROM   FI_CurrentReceiptData CR 
       LEFT JOIN Avanti_PODetails PD 
         ON CR.PONum = PD.PONumber 
       LEFT JOIN Avanti_POHeader PH 
         ON CR.PONum = PH.PONumber AND PD.PONumber = PH.PONumber
       LEFT JOIN Avanti_InventoryHeader IH 
         ON CR.ItemNumber = IH.ItemNumber   


संपादित करें 2:

ठीक है, तो आप जो कह रहे हैं, उसके अनुसार CR में 2 पंक्तियाँ हैं, और CR का PH से 1-से-1 संबंध है, और PH का PD से 1-से-अनेक संबंध है। और CR का IH से 1-टू-टी संबंध भी है। इस मामले में, यह मानते हुए कि आपके पास रेफरेंसियल अखंडता है, आप अपने जॉइन को इसमें बदल सकते हैं:


FROM   FI_CurrentReceiptData CR 
       LEFT JOIN Avanti_POHeader PH ON CR.PONum = PD.PONumber 
       INNER JOIN Avanti_PODetails PD ON PH.PONumber = PD.PONUmber
       LEFT JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber

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

लेकिन अब, यदि आपके पास CR में 2 पंक्तियाँ हैं, और प्रत्येक PONumbers में POHeader में 2 पंक्तियाँ हैं, और प्रत्येक POHeader में POdetails में 1 से अधिक पंक्तियाँ हैं, तो आपके पास निश्चित रूप से डुप्लिकेट होंगे। इससे बचने का वास्तव में कोई उपाय नहीं है। कारण यह है:

सीआर टेबल


PONum            ItemNumber
---------        ----------
123              ABC
456              DEF

पीएच तालिका


PONumber     
---------        
123              
456              

पीडी टेबल


PONumber     ItemNumber     
---------    -----------    
123          ABC    
123          ABC1
456          DEF
456          DEF1    

...यदि आप CR तालिका को PH तालिका में शामिल करते हैं, तो आपको केवल दो पंक्तियाँ मिलेंगी। यदि आप PH से PD टेबल में शामिल हो जाते हैं, तो आपको 4 पंक्तियाँ मिलेंगी। यदि आप सभी 3 को जोड़ते हैं, तो आपको 4 पंक्तियाँ भी मिलेंगी। शामिल होने की प्रकृति सभी तालिका में है, इसलिए जब आप सीआर तालिका से पीएच पर जाते हैं, तो उसे 2 पंक्तियों का परिणाम मिलता है ... और फिर वह परिणाम पीडी में शामिल हो जाता है, और वहां 4 पंक्तियां होती हैं। यदि आप पुष्टि कर सकते हैं कि आपका डेटा ऐसा है, तो आपको जो परिणाम मिल रहा है वह सही है।

3
M.R. 6 सितंबर 2011, 21:42
-हाँ, POHeader से PODetails एक 1-से-अनेक है। मैं इसे कैसे प्रतिबंधित कर सकता हूं? क्या ठीक करने के लिए बस मेरे जुड़ने को संशोधित करने के लिए वैसे भी है?
 – 
MAW74656
6 सितंबर 2011, 19:23
यह किस क्षेत्र से जुड़ता है? अर्थ, दोनों के बीच क्षेत्र संबंध क्या है?
 – 
M.R.
6 सितंबर 2011, 19:25
-POheader में PONumber होता है, PODetails में सभी संबंधित PONumbers होते हैं।
 – 
MAW74656
6 सितंबर 2011, 19:26
-आपके नवीनतम संपादन में अभी भी 4 रिकॉर्ड हैं। साथ ही, एक समय में FI_CurrentReceiptData में केवल 1 विशिष्ट PONumber होना चाहिए, इसलिए यह यहां कुछ नहीं करता है?
 – 
MAW74656
6 सितंबर 2011, 19:31
हम्म - किसी भी कारण से आप उन सभी के बीच बाएं शामिल हो रहे हैं? लेफ्ट जॉइन का उद्देश्य यह है कि आपको एक टेबल से सभी पंक्तियाँ मिलें, भले ही दूसरी तालिका में पंक्ति मिलान मौजूद हो। क्या 4 तालिकाओं के बीच कोई संदर्भात्मक अखंडता नहीं है? क्या कम से कम पीओ टेबल में रेफरेंसियल अखंडता है?
 – 
M.R.
6 सितंबर 2011, 19:33

चूंकि आप लेफ्ट जॉइन कर रहे हैं, आपको सभी मिलान रिकॉर्ड के लिए 1 पंक्ति वापस मिल जाएगी। तो आप जिन तालिकाओं में शामिल हो रहे हैं उनमें से एक 1 से अधिक पंक्ति लौटा रहा है।

कॉलम सूची में अन्य टेबल प्राथमिक कुंजी जोड़ने के लिए अपनी क्वेरी को अस्थायी रूप से बदलने का प्रयास करें और आपको जल्दी से यह बताने में सक्षम होना चाहिए कि कौन सी तालिका 1 से अधिक पंक्ति लौटा रही है।

1
PaulStock 6 सितंबर 2011, 19:18
@ पॉलस्टॉक- यहां कुछ भी खुलासा नहीं किया गया है, सीआर में 2 अलग-अलग आईडी हैं, पीडी 2, पीएच 1, आईएच 1, जैसे उन्हें होना चाहिए।
 – 
MAW74656
6 सितंबर 2011, 19:28