2011-06-09 10 views
7

मैंने http://www.artfulsoftware.com/mysqlbook/sampler/mysqled1ch20.htmlmysql में नेस्टेड सेट से निपटना?

का पालन करने का निर्णय लिया है तो अब मैं कोड के साथ कुछ मदद ढूंढ रहा हूं।

array('value' => 'Richard Shakespeare', 
     array('value' => 'Henry', 
      array('value' => 'Joan'), 
      array('value' => 'Margaret'), 
      array('value' => 'William', 
       array('value' => 'Susana', 
        array('value' => 'Elizabeth Hall', 
         array('value' => 'John Bernard'))), 
       array('value' => 'Hamnet'), 
       array('value' => 'Judith', 
        array('value' => 'Shakespeare Quiney'), 
        array('value' => 'Richard Quiney'), 
        array('value' => 'Thomas Quiney'))), 
      array('value' => 'Gilbert'), 
      array('value' => 'Joan', 
       array('value' => 'William Hart'), 
       array('value' => 'Mary Hart'), 
       array('value' => 'Thomas Hart'), 
       array('value' => 'Micheal Hart')), 
      array('value' => 'Anne'), 
      array('value' => 'Richard'), 
      array('value' => 'Edmond')), 
     array('value' => 'John')); 

तो अगर हम सम्मिलित करने के लिए कि डेटाबेस हम

के साथ समाप्त करना चाहते हैं में हैं:

मैं अपने डेटा, तो मेरी परीक्षण के लिए उपयोग कर रहा हूँ, मैं तो तरह किया जा रहा पेड़ कल्पना

Array 
(
    [0] => Array 
     (
      [value] => Richard Shakespeare 
      [left] => 1 
      [right] => 46 
     ) 

    [1] => Array 
     (
      [value] => Henry 
      [left] => 2 
      [right] => 43 
     ) 

    [2] => Array 
     (
      [value] => Joan 
      [left] => 3 
      [right] => 4 
     ) 

    [3] => Array 
     (
      [value] => Margaret 
      [left] => 5 
      [right] => 6 
     ) 

    [4] => Array 
     (
      [value] => William 
      [left] => 7 
      [right] => 24 
     ) 

    [5] => Array 
     (
      [value] => Susana 
      [left] => 8 
      [right] => 13 
     ) 

    [6] => Array 
     (
      [value] => Elizabeth Hall 
      [left] => 9 
      [right] => 12 
     ) 

    [7] => Array 
     (
      [value] => John Bernard 
      [left] => 10 
      [right] => 11 
     ) 

    [8] => Array 
     (
      [value] => Hamnet 
      [left] => 14 
      [right] => 15 
     ) 

    [9] => Array 
     (
      [value] => Judith 
      [left] => 16 
      [right] => 23 
     ) 

    [10] => Array 
     (
      [value] => Shakespeare Quiney 
      [left] => 17 
      [right] => 18 
     ) 

    [11] => Array 
     (
      [value] => Richard Quiney 
      [left] => 19 
      [right] => 20 
     ) 

    [12] => Array 
     (
      [value] => Thomas Quiney 
      [left] => 21 
      [right] => 22 
     ) 

    [13] => Array 
     (
      [value] => Gilbert 
      [left] => 25 
      [right] => 26 
     ) 

    [14] => Array 
     (
      [value] => Joan 
      [left] => 27 
      [right] => 36 
     ) 

    [15] => Array 
     (
      [value] => William Hart 
      [left] => 28 
      [right] => 29 
     ) 

    [16] => Array 
     (
      [value] => Mary Hart 
      [left] => 30 
      [right] => 31 
     ) 

    [17] => Array 
     (
      [value] => Thomas Hart 
      [left] => 32 
      [right] => 33 
     ) 

    [18] => Array 
     (
      [value] => Micheal Hart 
      [left] => 34 
      [right] => 35 
     ) 

    [19] => Array 
     (
      [value] => Anne 
      [left] => 37 
      [right] => 38 
     ) 

    [20] => Array 
     (
      [value] => Richard 
      [left] => 39 
      [right] => 40 
     ) 

    [21] => Array 
     (
      [value] => Edmond 
      [left] => 41 
      [right] => 42 
     ) 

    [22] => Array 
     (
      [value] => John 
      [left] => 44 
      [right] => 45 
     ) 

) 

तो इस मुद्दे को ध्यान में आता है, यह कैसे करना सबसे अच्छा है?

मेरे समाधान किया गया था:

$container = array(); 

function children($item){ 
    $children = 0; 
    foreach($item as $node) 
    if(is_array($node)) 
     $children += children($node)+1; 
    return $children; 
} 

function calculate($item, &$container, $data = array(0,0)){ 
    //althought this one is actually of no use, it could be useful as it contains a count 
    $data[0]++; //$left 

    $right = ($data[0]+(children($item)*2))+1; 

    //store the values in the passed container 
    $container[] = array(
    'value' => $item['value'], 
    'left' => $data[0], 
    'right' => $right, 
); 

    //continue looping 
    $level = $data[1]++; 
    foreach($item as &$node) 
    if(is_array($node)) 
     $data = calculate($node, $container, $data); 

    $data[1] = $level; 
    $data[0]++; 
    return $data; 
} 

calculate($tree, $container); 

यह कैसे कुशल है मैं नहीं जानता।

लेकिन अब प्रश्नों पर।

एक नोड के सभी सन्तान चयन करने के लिए हम

SELECT child.value AS 'Descendants of William', COUNT(*) AS `Level` 
FROM tester AS parent 
JOIN tester AS child ON child.`left` BETWEEN parent.`left` AND parent.`right` 
WHERE parent.`left` > 7 AND parent.`right` < 24 
GROUP BY child.value ORDER BY `level`; 

उपयोग कर सकते हैं एक नोड के सभी सन्तान चयन करने के लिए एक विशिष्ट गहराई तक, हम उपयोग कर सकते हैं
ध्यान दें कि हम गहराई तक विलियम के वंशज चयन कर रहे हैं 2 की
विलियम्स छोड़ दिया: 7, विलियम्स सही: 24, स्तर: 2

SELECT child.value AS 'Descendants of William', COUNT(*) AS `Level` 
FROM tester AS parent 
JOIN tester AS child ON child.`left` BETWEEN parent.`left` AND parent.`right` 
WHERE parent.`left` > 7 AND parent.`right` < 24 
GROUP BY child.value HAVING `level` <= 2 ORDER BY `level`; 

तो यह काफी आसान है।

लेकिन अब मैं कुछ बातें जानना चाहते हैं, तो
ध्यान दें कि वास्तविक डेटाबेस में और साथ ही वाम/सही सभी पंक्तियों में एक विशिष्ट आईडी है, और एक "जनक" उनके inviteers आईडी वाले कॉलम, या यदि अशक्त आमंत्रित नहीं

  • कहते हैं कि मैं Judith के एक बच्चे के रूप David सम्मिलित करना चाहते हैं, मैं ऐसा कैसे करते चलें?
  • आइए कहें कि मैं Mary Hart's अभिभावक और माता-पिता अभिभावक (array('Henery', 'Joan', 'Mary Hart')) प्राप्त करना चाहता हूं, मैं यह कैसे कर सकता हूं?
  • आइए कहें कि मैं William HartJoan से हटाना चाहता हूं, तो मैं ऐसा कैसे करता हूं?
+0

आपने क्या प्रयास किया है? मुझे पूछने से नफरत है, लेकिन नेस्टेड सेट जटिल हैं, और आपका प्रश्न लगता है जैसे आप भीड़ काम कर रहे हैं। इसके अलावा, आपने समस्या की कठिनाई को भी स्किम करना शुरू नहीं किया है। जैसे कि: "अगर मैं डेविड और जूडिथ को उलझाना चाहता हूं, तो जूडिथ अब बच्चे के रूप में डेविड की जगह लेता है और इसके विपरीत, मैं इसे कैसे कर सकता हूं [पेड़ को फिर से अनुक्रमणित किए बिना]?" –

उत्तर

1

अद्यतन/हटाने के लिए आपको शाखा के सभी तत्वों के left/right मूल्यों को बढ़ाने/घटाने की आवश्यकता होगी।
प्रश्नों के उदाहरण जिन्हें आप here पा सकते हैं।

मुझे कितना कुशल नहीं है।

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

+0

तो, यदि मैं किसी उपयोगकर्ता तालिका के साथ काम कर रहा हूं, इसलिए, डेटा अक्सर डाला जाएगा, अंत में सैकड़ों हजार पंक्तियां होंगी, लेकिन इसे अक्सर अपडेट/हटाया नहीं जाएगा, लेकिन लगभग हर पृष्ठ लोड पर पढ़ा जाएगा (वृक्ष संरचना हमारी साइट का एक केंद्रीय हिस्सा है) क्या मुझे नेस्टेड सेट के साथ जाना चाहिए? – Hailwood

+0

@OZ वास्तव में न केवल शाखा के तत्व बल्कि बाएं_आईडी> current_element.right_id वाले सभी तत्व। – malko

+0

@OZ_: मैं आपको डाउनवोट करता हूं क्योंकि यह MySQL के लिए सच नहीं है। हो सकता है कि यह PostGreSQL के लिए सच है और सेल्को भी यहां है। – Bytemain

0

यदि आप प्रत्येक रिश्ते के लिए डीएफएस का उपयोग करते हैं तो अपने सभी प्रश्नों को हल किया जा सकता है और फिर यदि आप इसे और अधिक विस्तृत करना चाहते हैं तो फिर से अपने फ़ंक्शन की गणना() का उपयोग करें।

+0

क्षमा करें, डीएफएस क्या है? – Hailwood

+0

हैलवुड: गहराई-प्रथम-खोज। – Bytemain

1
  • एक नोड आप के साथ नोड्स की जरूरत के माता-पिता को पाने के लिए left_id < child.left_id और right_id> child.right_id, आप केवल प्रत्यक्ष पूर्वज उच्चतम left_id के साथ पिछले सेट से एक को चुनना चाहते हैं।

  • एक नोड को हटाने के लिए इसे हटा दें और फिर हटाए गए तत्व दाएं आईडी से अधिक सभी बाएं/दाएं आईडी को दो बार कम करें। अगर (leftId> delete.leftId) leftId- = 2 दाएं के लिए समान है

  • नोड डालने के लिए बाएं आईडी> parent.rightId के बाद सभी नोड्स में + 2 जोड़ने के लिए कुछ जगह बनाएं, तो parent.rightId + = 2 फिर डालें leftId = parent.rightId-2 के साथ नोड और दाएं आईडी = parent.rightId-1

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