2009-01-23 16 views
6

मैं एक एसक्यूएल तालिका इसलिए की तरह है मैं मूल डेटा का मौजूदा पदानुक्रमिक प्रवृत्ति (राज्य, शहर, स्कूल) तथ्य यह है कि एक साधारण रिश्ते के बीच की जरूरत है फीका है के रूप में उदाहरण तालिका बदल रहा हूँ सामान।एकल SQL तालिका में रिकॉर्ड्स के बीच कई से अधिक संबंधों का प्रतिनिधित्व करने का सबसे अच्छा तरीका क्या है?</p> <p>अपडेट::

entities 
id  name    
1  Apple  
2  Orange    
3  Banana    
4  Carrot     
5  Mushroom   

मैं इन संस्थाओं के बीच दो तरह के रिश्तों को परिभाषित करने के तो एक उपयोगकर्ता एक इकाई को देखने के सभी संबंधित संस्थाओं की एक सूची देख सकते हैं चाहता हूँ।

संबंध अंतिम उपयोगकर्ता द्वारा परिभाषित किए जाते हैं।

डेटाबेस में इन रिश्तों का प्रतिनिधित्व करने का सबसे अच्छा तरीका क्या है और बाद में क्वेरी और उन्हें अपडेट करें?

एक तरह से मैं इसे देख के रूप में ...

मेरे वृत्ति एक रिश्ता तालिका इसलिए की तरह कहते हैं:

entity_entity 
entity_id_a  entity_id_b 
1     2 
5     1 
4     1 
5     4 
1     3 

मामले जा रहा है, 4 के एक आपूर्ति की ENTITY_ID यह देखते हुए कि, कैसे एक होगा सभी संबंधित रिकॉर्ड प्राप्त करें, जो 1 और 5 होगा?

इसी तरह ENTITY_ID = 1 के एक प्रश्न लौटना चाहिए अपने समय के लिए 2, 3, 4, और 5

धन्यवाद और मुझे पता है कि अगर मैं बिल्कुल भी प्रश्न को स्पष्ट कर सकते हैं।

उत्तर

11

एक बाधा परिभाषित करें: entity_id_a < entity_id_b

अनुक्रमणिका बनाएँ:

CREATE UNIQUE INDEX ix_a_b ON entity_entity(entity_id_a, entity_id_b); 
CREATE INDEX ix_b ON entity_entity(entity_id_b); 

दूसरा सूचकांक entity_id_a शामिल करने के लिए के रूप में आप यह केवल का उपयोग करेगा एक b के भीतर सभी a के चयन करने की आवश्यकता नहीं है। RANGE SCANix_b पर SKIP SCAN से ix_a_b पर तेज़ होगा। इस प्रकार

अपने संस्थाओं के साथ तालिका भरें:

INSERT 
INTO entity_entity (entity_id_a, entity_id_b) 
VALUES (LEAST(@id1, @id2), GREATEST(@id1, @id2)) 

तब का चयन करें:

SELECT entity_id_b 
FROM entity_entity 
WHERE entity_id_a = @id 
UNION ALL 
SELECT entity_id_a 
FROM entity_entity 
WHERE entity_id_b = @id 

UNION ALL यहाँ की मदद से आप अनुक्रमित ऊपर का उपयोग करें और विशिष्टता के लिए अतिरिक्त छंटाई से बचें।

उपरोक्त सभी एक सममित और विरोधी रिफ्लेक्सिव रिश्ते के लिए मान्य है।इसका मतलब है कि:

  • तो एक से संबंधित है, तो से संबंधित है एक

  • एकएक

  • से संबंधित कभी नहीं किया गया है
+0

यह दृष्टिकोण अभ्यास में बहुत अच्छी तरह से काम कर रहा है। बहुत धन्यवाद। – GloryFish

1

मुझे लगता है कि आपके द्वारा सुझाई गई संरचना ठीक है।

संबंधित रिकॉर्ड

SELECT related.* FROM entities AS search 
LEFT JOIN entity_entity map ON map.entity_id_a = search.id 
LEFT JOIN entities AS related ON map.entity_id_b = related.id 
WHERE search.name = 'Search term' 

आशा है कि मदद करता है की तरह कुछ कर पाने के लिए।

+0

क्या होगा यदि मेरे खोज शब्द का एक इकाई जिसका आईडी में केवल entity_id_b में होता है से मेल खाता है नक्शा? –

+0

दूसरे शब्दों में, आपकी क्वेरी केवल तभी काम करती है जब हर रिश्ते दो बार संग्रहीत हो, रिवर्स। जैसे (1,4) और (4,1)। –

0
select * from entities 
where entity_id in 
(
    select entity_id_b 
    from entity_entity 
    where entity_id_a = @lookup_value 
) 
0

मैं कुछ तरीकों से सोच सकता हूं।

एक मामले के साथ एक एकल पास:

SELECT DISTINCT 
    CASE 
     WHEN entity_id_a <> @entity_id THEN entity_id_a 
     WHEN entity_id_b <> @entity_id THEN entity_id_b 
    END AS equivalent_entity 
FROM entity_entity 
WHERE entity_id_a = @entity_id OR entity_id_b = @entity_id 

या दो से फ़िल्टर प्रश्नों UNIONed इस प्रकार:

SELECT entity_id_b AS equivalent_entity 
FROM entity_entity 
WHERE entity_id_a = @entity_id 
UNION 
SELECT entity_id_a AS equivalent_entity 
FROM entity_entity 
WHERE entity_id_b = @entity_id 
1

लिंक तालिका दृष्टिकोण, ठीक लग रहा है, सिवाय इसके कि आप एक 'संबंध प्रकार' चाहते हो सकता है तो कि आप जानते हैं कि वे क्यों संबंधित हैं।

उदाहरण के लिए, रैले और उत्तरी केरोलिना के बीच संबंध रैले और डरहम के बीच एक रिश्ता के रूप में ही नहीं है। इसके अतिरिक्त, आप जानना चाहेंगे कि रिश्ते में 'माता-पिता' कौन है, यदि आप सशर्त ड्रॉप-डाउन चला रहे थे। (यानी आप एक राज्य का चयन करते हैं, आप राज्य में रहने वाले शहरों को देखते हैं)।

आपकी आवश्यकताओं की जटिलता के आधार पर, आपके पास अभी सरल सेटअप पर्याप्त नहीं हो सकता है। यदि आपको बस यह दिखाने की ज़रूरत है कि दो रिकॉर्ड किसी तरह से संबंधित हैं, तो लिंक तालिका पर्याप्त होनी चाहिए।

+0

मुझे लगता है कि आप क्या प्राप्त कर रहे हैं। इस मामले में हम विशेष रूप से पदानुक्रम का प्रतिनिधित्व नहीं कर रहे हैं। इस प्रणाली में केवल एक ही राज्य होगा और रिश्तों का उपयोग ड्रिल-डाउन स्टाइल नेविगेशन के लिए नहीं किया जाएगा। – GloryFish

1

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

मदों में (गैर-अतिव्यापी) तुल्यता कक्षाओं हैं, तो आप तुल्यता कक्षाओं तालिका डिजाइन, जहां कक्षा में सब कुछ बराबर माना जाता है के लिए आधार बनाने के लिए चाहते हो सकता है। कक्षाओं के लिए खुद को गुमनाम हो सकते हैं:

CREATE TABLE equivalence_class (
    class_id int -- surrogate, IDENTITY, autonumber, etc. 
    ,entity_id int 
) 

entity_id अपने अंतरिक्ष के एक गैर-अतिव्यापी विभाजन के लिए अद्वितीय होना चाहिए।

यह उचित बाईं या दाएं हाथ सत्ता सुनिश्चित या एक ऊपरी-दाएँ संबंध मैट्रिक्स के लिए मजबूर करने की समस्या से बचा जाता है।

तो आपकी क्वेरी थोड़ा अलग है:

SELECT c2.entity_id 
FROM equivalence_class c1 
INNER JOIN equivalence_class c2 
    ON c1.entity_id = @entity_id 
    AND c1.class_id = c2.class_id 
    AND c2.entity_id <> @entity_id 

या, समतुल्य रूप:

SELECT c2.entity_id 
FROM equivalence_class c1 
INNER JOIN equivalence_class c2 
    ON c1.entity_id = @entity_id 
    AND c1.class_id = c2.class_id 
    AND c2.entity_id <> c1.entity_id 
+0

अच्छा! आप सी 2.entity_id <> c1.entity_id का परीक्षण भी कर सकते हैं, c2.entity_id <> @entity_id के बजाय। इस तरह आपको @entity_id पैरामीटर को दो बार पास करने की आवश्यकता नहीं है। –

+0

मुझे लगता है कि यह एक संग्रहीत प्रक्रिया होगी, लेकिन हां, यह पैरामीटरयुक्त विज्ञापन प्रश्न पूछने वाले भक्तों के बराबर होगा। –

-1

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

0

अपने अद्यतन स्कीमा के आधार पर इस क्वेरी काम करना चाहिए:

select if(entity_id_a=:entity_id,entity_id_b,entity_id_a) as related_entity_id where :entity_id in (entity_id_a, entity_id_b) 

जहां: ENTITY_ID इकाई आप जानना चाहते हैं के लिए बाध्य है