डेटाबेस डिजाइन: "(कई-से-कई) -to-many" रिश्ते को सामान्य करना


14

लघु संस्करण

मुझे एक मौजूदा कई-से-कई सम्मिलित होने के लिए प्रत्येक जोड़ी में एक निश्चित संख्या में अतिरिक्त गुणों को जोड़ना होगा। नीचे दिए गए आरेखों के लिए, विकल्प 1-4 में से कौन सा सबसे अच्छा तरीका है, फायदे और नुकसान के मामले में, बेस केस का विस्तार करके इसे पूरा करने के लिए? या, वहाँ एक बेहतर विकल्प मैं यहाँ पर विचार नहीं किया है?

लंबा संस्करण

मेरे पास वर्तमान में एक इंटरमीडिएट जॉइन टेबल के माध्यम से कई-से-कई संबंधों में दो तालिकाओं हैं। अब मुझे उन संपत्तियों के अतिरिक्त लिंक जोड़ने की आवश्यकता है जो मौजूदा वस्तुओं की जोड़ी से संबंधित हैं। मेरे पास प्रत्येक जोड़ी के लिए इन गुणों की एक निश्चित संख्या है, हालांकि संपत्ति तालिका में एक प्रविष्टि कई जोड़े (या यहां तक ​​कि एक जोड़ी के लिए कई बार उपयोग की जा सकती है) पर लागू हो सकती है। मैं यह करने के लिए सबसे अच्छा तरीका निर्धारित करने की कोशिश कर रहा हूं, और स्थिति के बारे में सोचने के तरीके को छांटने में परेशानी हो रही है। शब्दशः ऐसा लगता है जैसे मैं इसका वर्णन निम्न में से किसी एक के रूप में कर सकता हूँ:

  1. एक जोड़ी अतिरिक्त संपत्तियों की निश्चित संख्या के एक सेट से जुड़ी
  2. एक जोड़ा कई अतिरिक्त गुणों से जुड़ा हुआ है
  3. गुणों के एक सेट से जुड़ी कई (दो) वस्तुएं
  4. कई वस्तुओं को कई गुणों से जोड़ा जाता है

उदाहरण

मेरे पास दो ऑब्जेक्ट प्रकार हैं, एक्स और वाई, प्रत्येक में अद्वितीय आईडी, और objx_objyकॉलम के साथ एक लिंकिंग टेबल x_idऔर y_id, जो एक साथ लिंक के लिए प्राथमिक कुंजी बनाते हैं। प्रत्येक X कई Ys से संबंधित हो सकता है, और इसके विपरीत। यह मेरे मौजूदा कई-से-कई संबंधों के लिए सेटअप है।

मुख्य मामला

मुख्य मामला

अब इसके अतिरिक्त मेरे पास एक अन्य तालिका में परिभाषित गुणों का एक समूह है, और एक शर्त है जिसके तहत किसी दिए गए (एक्स, वाई) जोड़े के पास संपत्ति पी होनी चाहिए। शर्तों की संख्या निर्धारित है, और सभी जोड़ों के लिए समान है। वे मूल रूप से कहते हैं "स्थिति C1 में, जोड़ी (X1, Y1) के पास संपत्ति P1 है", "स्थिति C2 में, जोड़ी (X1, Y1) के पास संपत्ति P2 है", और इसी तरह, प्रत्येक जोड़ी के लिए तीन स्थितियों / शर्तों के लिए। तालिका।

विकल्प 1

मेरे वर्तमान स्थिति में वास्तव में तीन तरह की स्थितियों देखते हैं, और इसलिए एक संभावना स्तंभ जोड़ने का है मैं, कि वृद्धि की उम्मीद करने का कोई कारण नहीं है c1_p_id, c2_p_idऔर c3_p_idकरने के लिए featx_featy, किसी दिए गए के लिए निर्दिष्ट करने x_idऔर y_idजो संपत्ति, p_idतीन मामलों में से प्रत्येक में उपयोग करने के लिए ।

विकल्प 1

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

विकल्प 2

एक शर्त तालिका बनाएँ cond, और शामिल होने की मेज की प्राथमिक कुंजी के लिए शर्त आईडी जोड़ें।

विकल्प 2

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

SELECT objx.*, objy.* FROM objx
  INNER JOIN objx_objy ON objx_objy.x_id = objx.id
  INNER JOIN objy ON objy.id = objx_objy.y_id

फिर मुझे DISTINCTडुप्लिकेट प्रविष्टियों से बचने के लिए एक खंड जोड़ना होगा । ऐसा लगता है कि प्रत्येक जोड़ी को केवल एक बार मौजूद होना चाहिए।

विकल्प 3

ज्वाइन टेबल में एक नई 'पेयर आईडी' बनाएं, और फिर पहले वाले और प्रॉपर्टीज और कंडीशन के बीच एक दूसरी लिंक टेबल रखें।

विकल्प 3

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

विकल्प 4 (3 बी)

मूल रूप से विकल्प 3 के समान है, लेकिन अतिरिक्त आईडी फ़ील्ड के निर्माण के बिना। यह दोनों मूल आईडी को नई जॉइन टेबल में डालकर पूरा किया जाता है, इसलिए इसमें इसके बजाय फ़ील्ड x_idऔर y_idफ़ील्ड शामिल हैं xy_id

विकल्प 4

इस रूप में एक अतिरिक्त लाभ यह है कि यह मौजूदा तालिकाओं में बदलाव नहीं करता है (हालांकि वे अभी तक उत्पादन में नहीं हैं)। हालाँकि, यह मूल रूप से एक पूरी तालिका को कई बार दोहराता है (या वैसे भी, वैसे भी) ऐसा लगता है कि आदर्श भी नहीं है।

सारांश

मेरी भावना यह है कि विकल्प 3 और 4 समान हैं कि मैं किसी एक के साथ जा सकता हूं। मैं शायद अब तक होता अगर संपत्तियों की एक छोटी, निश्चित संख्या की आवश्यकता के लिए नहीं, जो विकल्प 1 बनाता है और अधिक उचित लगता है, अन्यथा यह होगा। कुछ बहुत ही सीमित परीक्षण के आधार पर, DISTINCTमेरे प्रश्नों का एक खंड जोड़ने से इस स्थिति में प्रदर्शन प्रभावित नहीं होता है, लेकिन मुझे यकीन नहीं है कि विकल्प 2 स्थिति के साथ-साथ दूसरों को भी दर्शाता है, क्योंकि अंतर्निहित दोहराव के कारण होता है लिंक तालिका की कई पंक्तियों में समान (X, Y) जोड़े।

क्या इन विकल्पों में से एक मेरा सबसे अच्छा तरीका है, या क्या कोई अन्य संरचना है जिस पर मुझे विचार करना चाहिए?


कुल मिलाकर 1 और 4 सबसे अच्छे विकल्प लगते हैं, मैं सहमत हूं। विकल्प 4 के साथ गुणों की निश्चित (3) संख्या को लागू करना आसान नहीं होगा, लेकिन मुझे लगता है कि यह संभव है।
ypercube y

के लिए DISTINCTखंड, मैं # 2 के अंत में एक है, जो लिंक की तरह एक प्रश्न के बारे में सोच रहा था xऔर yके माध्यम से xyc, लेकिन का उल्लेख नहीं करता cहै, तो मैं कर दिया है ... तो (x_id, y_id, c_id)विवश UNIQUEपंक्तियों के साथ (1,1,1)और (1,1,2)फिर, SELECT x.id, y.id FROM x JOIN xyc JOIN y, मैं वापस मिल जाएगा दो समान पंक्तियाँ, (1,1)और (1,1)
माइकल अंडरवुड

1
आह अच्छा। मैं वैसे भी विकल्प 2 को खारिज कर दूंगा। मैं 1 या 4 के साथ जाना चाहता हूँ
ypercube

जितना मैं इसके बारे में सोचता हूं, उतना ही मुझे लगता है कि गुणों की संख्या को तीन तक सीमित करना मेरी आवश्यकताओं में से सबसे कम महत्वपूर्ण है। इसलिए अगले थोड़े समय में अतिरिक्त रचनात्मक प्रतिक्रिया को रोकते हुए, मैं शायद इस बिंदु पर # 4 के साथ जाऊंगा। आपके इनपुट के लिए धन्यवाद, @ypercube!
माइकल अंडरवुड

जवाबों:


7
  • विकल्प 1

    * यह मेरे लिए एक महान विचार की तरह प्रतीत नहीं होता है, क्योंकि यह SQL को एक विशेषता पर लागू सभी गुणों का चयन करने के लिए जटिल करता है ...

    यह जरूरी नहीं कि क्वेरी क्वेरी SQL (नीचे निष्कर्ष देखें)।

    ... और अधिक परिस्थितियों के लिए आसानी से पैमाने नहीं है ...

    यह अधिक परिस्थितियों तक आसानी से पहुंचता है, जब तक कि अभी भी एक निश्चित संख्या में स्थितियां हैं, और दर्जनों या सैकड़ों नहीं हैं।

    हालांकि, यह प्रति (एक्स, वाई) जोड़ी की एक निश्चित संख्या की आवश्यकता को लागू करता है। वास्तव में, यह यहां एकमात्र विकल्प है जो ऐसा करता है। *

    यह करता है, और यद्यपि आप एक टिप्पणी में कहते हैं कि यह "मेरी आवश्यकताओं में सबसे कम महत्वपूर्ण है", आपने कहा है कि यह बिल्कुल भी मायने नहीं रखता है।

  • विकल्प 2

    एक नकारात्मक पक्ष यह है कि यह प्रत्येक जोड़ी के लिए शर्तों की संख्या निर्दिष्ट नहीं करता है। एक और बात यह है कि जब मैं केवल प्रारंभिक संबंध पर विचार कर रहा हूं ... तो मुझे डुप्लिकेट प्रविष्टियों से बचने के लिए एक DISTINCT क्लॉज जोड़ना होगा ...

    मुझे लगता है कि आपके द्वारा उल्लिखित जटिलताओं के कारण आप इस विकल्प को खारिज कर सकते हैं। objx_objyतालिका (उदाहरण के लिए "सभी का चयन करें गुण एक सुविधा पर लागू" है, जो मैं सभी गुण मतलब करने के लिए ले रहा हूँ एक के लिए लागू आपके प्रश्नों में से कुछ के लिए ड्राइविंग तालिका होने की संभावना है objxया objy)। आप पहले से आवेदन करने के लिए एक दृश्य का उपयोग कर सकते हैं, DISTINCTइसलिए यह जटिल प्रश्नों का मामला नहीं है, लेकिन यह बहुत कम लाभ के लिए बहुत बुरी तरह से प्रदर्शन-वार पैमाने पर जा रहा है।

  • विकल्प 3

    हालांकि यह एक नई आईडी बनाने के लिए समझ में आता है जो मौजूदा आईडी के अलावा और कुछ नहीं की पहचान करता है?

    नहीं, यह नहीं है - विकल्प 4 हर संबंध में बेहतर है।

  • विकल्प 4

    ... यह मूल रूप से एक पूरी तालिका को कई बार दोहराता है (या वैसे भी, वैसे भी) ऐसा लगता है कि आदर्श भी नहीं है।

    यह विकल्प बस ठीक है - यह संबंधों को स्थापित करने का स्पष्ट तरीका है यदि गुणों की संख्या परिवर्तनशील है या परिवर्तन के अधीन है

निष्कर्ष

मेरी प्राथमिकता विकल्प 1 होगी यदि प्रति संपत्तियों की संख्या objx_objyस्थिर होने की संभावना है, और यदि आप कभी भी एक मुट्ठी भर अतिरिक्त जोड़ने की कल्पना नहीं कर सकते हैं। यह एकमात्र विकल्प भी है जो 'गुणों की संख्या = 3' बाधा को लागू करता है - विकल्प 4 पर इसी तरह की बाधा को लागू करने से संभवतः c1_p_idxy तालिका में कॉलम जोड़ने की संभावना है *।

यदि आप वास्तव में उस स्थिति के बारे में अधिक परवाह नहीं करते हैं, और आपके पास यह संदेह करने का कारण भी है कि गुणों की संख्या स्थिर होने वाली है तो विकल्प 4 चुनें।

यदि आप निश्चित नहीं हैं कि विकल्प 1 चुनें - यह सरल है और यदि आपके पास विकल्प है तो निश्चित रूप से बेहतर है, जैसा कि अन्य लोगों ने कहा है। यदि आपको विकल्प 1 बंद कर दिया जाता है ... क्योंकि यह एसक्यूएल को एक विशेषता पर लागू सभी गुणों का चयन करने के लिए जटिल करता है ... "मैं सुझाव देता हूं कि विकल्प 4 में अतिरिक्त तालिका के समान डेटा प्रदान करने के लिए एक दृश्य बनाएं:

विकल्प 1 टेबल:

create table prop(id integer primary key);
create table objx(id integer primary key);
create table objy(id integer primary key);

create table objx_objy(
  x_id integer references objx
, y_id integer references objy
, c1_p_id integer not null references prop
, c2_p_id integer not null references prop
, c3_p_id integer not null references prop
, primary key (x_id, y_id)
);

insert into prop(id) select generate_series(90,99);
insert into objx(id) select generate_series(10,12);
insert into objy(id) select generate_series(20,22);

insert into objx_objy(x_id,y_id,c1_p_id,c2_p_id,c3_p_id)
select objx.id, objy.id, 90, 91, 90+floor(random()*10)
from objx cross join objy;

4 विकल्प 'अनुकरण' को देखें:

create view objx_objy_prop as
select x_id
     , y_id
     , unnest(array[1,2,3]) c_id
     , unnest(array[c1_p_id,c2_p_id,c3_p_id]) p_id
from objx_objy;

"एक सुविधा के लिए लागू सभी गुणों का चयन करें":

select distinct p_id from objx_objy_prop where x_id=10 order by p_id;

/*
|p_id|
|---:|
|  90|
|  91|
|  97|
|  98|
*/

यहाँ dbfiddle


-3

मेरा मानना ​​है कि इनमें से कोई भी विकल्प काम कर सकता है, लेकिन मैं विकल्प 1 के साथ जाऊंगा यदि शर्तों की संख्या 3 पर सही मायने में तय की गई है, और विकल्प 2 यदि ऐसा नहीं है। ओकाम का रेजर डेटाबेस डिजाइन के लिए भी काम करता है, अन्य सभी कारक जो सबसे सरल डिजाइन के बराबर होते हैं, आमतौर पर सबसे अच्छे होते हैं।

यद्यपि यदि आप सख्त डेटाबेस सामान्यीकरण नियमों का पालन करना चाहते हैं, तो मेरा मानना ​​है कि शर्तों की संख्या निर्धारित होने के बावजूद आपको 2 के साथ जाने की आवश्यकता होगी।

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