एक ही तालिका में दो बार शामिल होने का सबसे अच्छा तरीका क्या है?


108

यह थोड़ा जटिल है, लेकिन मेरे पास 2 टेबल हैं। मान लीजिए कि संरचना कुछ इस प्रकार है:

*Table1*
ID
PhoneNumber1
PhoneNumber2

*Table2*
PhoneNumber
SomeOtherField

तालिकाओं को Table1.PhoneNumber1 -> Table2.PhoneNumber, या Table1.PhoneNumber2 -> Table2.PhoneNumber के आधार पर जोड़ा जा सकता है।

अब, मैं एक परिणाम प्राप्त करना चाहता हूं जिसमें PhoneNumber1, SomeOtherField शामिल है जो PhoneNumber1, PhoneNumber2 और SomeOtherField से मेल खाती है जो PhoneNumber2 से मेल खाती है।

मैंने इसे करने के 2 तरीकों के बारे में सोचा - या तो दो बार तालिका में शामिल होने से, या एक बार ओआरएस क्लॉज में शामिल होने से।

विधि 1 :

SELECT t1.PhoneNumber1, t1.PhoneNumber2, 
   t2.SomeOtherFieldForPhone1, t3.someOtherFieldForPhone2
FROM Table1 t1
INNER JOIN Table2 t2
   ON t2.PhoneNumber = t1.PhoneNumber1
INNER JOIN Table2 t3
   ON t3.PhoneNumber = t1.PhoneNumber2

यह काम करने लगता है।

विधि 2 :

किसी तरह एक क्वेरी है कि इस तरह से एक सा लग रहा है -

SELECT ...
FROM Table1
INNER JOIN Table2 
   ON Table1.PhoneNumber1 = Table2.PhoneNumber OR
      Table1.PhoneNumber2 = Table2.PhoneNumber

मैंने अभी तक यह काम नहीं किया है और मुझे यकीन नहीं है कि ऐसा करने का कोई तरीका है।

इसे पूरा करने का सबसे अच्छा तरीका क्या है? न तो रास्ता सरल या सहज लगता है ... क्या ऐसा करने के लिए अधिक सरल तरीका है? इस आवश्यकता को आम तौर पर कैसे लागू किया जाता है?

जवाबों:


151

सबसे पहले, मैं कोशिश करूंगा और इन तालिकाओं को प्राकृतिक कुंजी के रूप में फोन नंबरों का उपयोग करने से दूर कर दूंगा। मैं प्राकृतिक कुंजियों का प्रशंसक नहीं हूं और यह एक महान उदाहरण है कि क्यों। प्राकृतिक कुंजी, विशेष रूप से फोन नंबर जैसी चीजें बदल सकती हैं और अक्सर ऐसा होता है। उस परिवर्तन के होने पर अपने डेटाबेस को अपडेट करना एक बहुत बड़ा, त्रुटि-प्रवण सिरदर्द होगा। *

विधि 1 जैसा कि आप वर्णन करते हैं कि यह आपकी सबसे अच्छी शर्त है। नामकरण योजना और छोटे उपनामों के कारण यह थोड़ा उलझा हुआ लगता है लेकिन ... अलियासिंग आपका मित्र है जब यह एक ही तालिका में कई बार शामिल होने या उपश्रेणियों आदि का उपयोग करने के लिए आता है।

मैं बस चीजों को थोड़ा साफ करूंगा:

SELECT t.PhoneNumber1, t.PhoneNumber2, 
   t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2
FROM Table1 t
JOIN Table2 t1 ON t1.PhoneNumber = t.PhoneNumber1
JOIN Table2 t2 ON t2.PhoneNumber = t.PhoneNumber2

मैंने क्या किया:

  • INNER को निर्दिष्ट करने की आवश्यकता नहीं है - यह इस तथ्य से निहित है कि आप LEFT या RIGHT निर्दिष्ट नहीं करते हैं
  • अपनी प्राथमिक लुकअप तालिका को n-प्रत्यय न करें
  • N-Suffix टेबल अलायस जिसे आप स्पष्ट करने के लिए कई बार उपयोग करेंगे

* एक तरह से डीबीए प्राकृतिक कुंजी को अद्यतन करने के सिरदर्द से बचता है, प्राथमिक कुंजी और विदेशी कुंजी बाधाओं को निर्दिष्ट नहीं करना है जो खराब डीबी डिजाइन के साथ मुद्दों को आगे बढ़ाते हैं। मैंने वास्तव में इसे अधिक बार नहीं देखा है।


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

6
@volumeone - मुझे लगता है कि आपने मेरे उत्तर के अंतिम भाग को गलत समझा होगा। प्राथमिक और विदेशी कुंजी हैं एक अच्छा विचार। उनसे बचना खराब अभ्यास, खराब डिजाइन और सिर्फ सादा बुरा है।
पॉल सासिक

बिल्कुल सही..लेकिन क्यों इस स्थिति में उपनाम एक होना चाहिए?
रेडियन कोर

क्या एक ही तालिका में दो बार शामिल होने के बिना ऐसा करने का कोई तरीका है? शायद एक ऐसी स्थिति का उपयोग करें जहाँ खण्ड में ...
JohnOsborne

5

पहला अच्छा है जब तक कि या तो Phone1 या (अधिक संभावना है) phone2 शून्य हो सकता है। उस मामले में आप एक आंतरिक जुड़ाव के बजाय एक वामपंथी जुड़ाव का उपयोग करना चाहते हैं।

यह आमतौर पर एक बुरा संकेत है जब आपके पास दो फोन नंबर फ़ील्ड वाली एक तालिका होती है। आमतौर पर इसका मतलब है कि आपके डेटाबेस का डिज़ाइन त्रुटिपूर्ण है।


महान बिंदु! यह मुझे बाद में बड़े सिरदर्द का कारण बना ... धन्यवाद!
14

4

आप UNIONदो जोड़ों को संयोजित करने के लिए उपयोग कर सकते हैं :

SELECT Table1.PhoneNumber1 as PhoneNumber, Table2.SomeOtherField as OtherField
  FROM Table1
  JOIN Table2
    ON Table1.PhoneNumber1 = Table2.PhoneNumber
 UNION
SELECT Table1.PhoneNumber2 as PhoneNumber, Table2.SomeOtherField as OtherField
  FROM Table1
  JOIN Table2
    ON Table1.PhoneNumber2 = Table2.PhoneNumber

1
मैंने इस बारे में सोचा, लेकिन मुझे इसकी आवश्यकता है कि इसे एक एकल रिकॉर्ड के रूप में लौटाया जाए ...
फ्रैडी

ओह ठीक है, मैं बहुत विपरीत माना। अगर ऐसा है तो मैं इसे आपके पहले तरीके की तरह इस्तेमाल करूँगा। मैं अपना उत्तर संपादित करूँगा।
पॉइंट

3

मेरी समस्या यह थी कि यदि कोई या केवल एक फ़ोन नंबर मौजूद हो (पूर्ण पता पुस्तिका) , तो भी रिकॉर्ड प्रदर्शित करना था । इसलिए मैंने एक लेफ्टिनेंट जिन्न का उपयोग किया जो बाएं से सभी रिकॉर्ड लेता है, भले ही कोई भी दाईं ओर मौजूद न हो। मेरे लिए यह Microsoft Access SQL में काम करता है (उन्हें कोष्ठक की आवश्यकता है!)

SELECT t.PhoneNumber1, t.PhoneNumber2, t.PhoneNumber3
   t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2, t3.someOtherFieldForPhone3
FROM 
(
 (
  Table1 AS t LEFT JOIN Table2 AS t3 ON t.PhoneNumber3 = t3.PhoneNumber
 )
 LEFT JOIN Table2 AS t2 ON t.PhoneNumber2 = t2.PhoneNumber
)
LEFT JOIN Table2 AS t1 ON t.PhoneNumber1 = t1.PhoneNumber;

2

पहली विधि उचित दृष्टिकोण है और वह करेगी जो आपको चाहिए। हालाँकि, आंतरिक जोड़ के साथ, आप केवल तभी पंक्तियों का चयन करेंगे Table1जब दोनों फ़ोन नंबर मौजूद हों Table2। आप ऐसा करना चाहते हैं LEFT JOINताकि सभी पंक्तियों Table1को चुना जा सके। यदि फोन नंबर मेल नहीं खाते हैं, तो SomeOtherFieldएस शून्य होगा। यदि आप यह सुनिश्चित करना चाहते हैं कि आपके पास कम से कम एक मिलान वाला फ़ोन नंबर है तो आप कर सकते हैंWHERE t2.PhoneNumber IS NOT NULL OR t3.PhoneNumber IS NOT NULL

दूसरी विधि में एक समस्या हो सकती है: क्या होता है अगर Table2दोनों PhoneNumber1और PhoneNumber2? किस पंक्ति का चयन किया जाएगा? आपके डेटा, विदेशी कुंजियों आदि के आधार पर, यह समस्या हो सकती है या नहीं भी हो सकती है।

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