SitePoint Sponsor

User Tag List

Page 2 of 5 FirstFirst 12345 LastLast
Results 26 to 50 of 103
  1. #26
    SitePoint Guru nagrom's Avatar
    Join Date
    Jul 2001
    Location
    Western CT, USA
    Posts
    803
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by samsm
    Take a gander at the links in post 4. ;-)
    whoops! sorry sam.....hehe

    it's worth noting *that* method (the sqlteam lineage one), also falls apart at some point. i played around with it about 6 months ago, and the lineages can get out of hand pretty quickly. SQL Server has an 8000 character limit on varchar fields, and sorting by such huge monsters will eventually bog down the system.

    but still, it's neat stuff. joe celko is supposed to have a new book out soon that covers all the different tree methods he's gathered over the years. i'm sure it will be on the top shelf of my porcelain library.

  2. #27
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by nagrom
    but still, it's neat stuff. joe celko is supposed to have a new book out soon that covers all the different tree methods he's gathered over the years. i'm sure it will be on the top shelf of my porcelain library.
    That sounds very cool. I have a library copy of SQL for Smarties I need to return today... was considering purchasing. That new book sounds quite interesting though, I had not heard about it. Any links on it?
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  3. #28
    SitePoint Guru nagrom's Avatar
    Join Date
    Jul 2001
    Location
    Western CT, USA
    Posts
    803
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sorry no.... there is a hint by celko in the comments of the sqlteam article. i emailed him a few months back about a tree question and he mentioned finishing the manuscript by jan 1, so....

  4. #29
    SitePoint Member
    Join Date
    Apr 2003
    Location
    the Netherlands
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by website
    PHP Code:
    Array (
        [
    name] => SomeTopTreeName;
        [
    id] => {theIdInTheDB};
        [
    subtree] => Array(
            [
    name] => SomeSubTreeName;
            [
    id] => {theIdInTheDB};
            [
    subtree] => Array(
                
    etc...
            )
        ) 
    This modified version of the display_tree() function used in the article, returns this type of array. (It only returns the 'title' field of each node, as that's the only information in my table. It's very easy to add other fields: just modify the array('title'=>$row['title']) part.)

    PHP Code:
    function get_tree($root) {
       
    // retrieve the left and right value of the $root node
       
    $result mysql_query('SELECT lft, rgt FROM tree '.
                              
    'WHERE title="'.$root.'";');
       
    $row mysql_fetch_array($result);

       
    // start with an empty $right stack
       
    $right = array();

       
    // our tree
       
    $tree = array();

       
    // this stack will point to the right subtree
       
    $pathstack = array(&$tree);

       
    // now, retrieve all descendants of the $root node
       
    $result mysql_query('SELECT title, lft, rgt FROM tree '.
                              
    'WHERE lft BETWEEN '.$row['lft'].' AND '.
                              
    $row['rgt'].' ORDER BY lft ASC;');

       
    // display each row
       
    while ($row mysql_fetch_array($result)) {
           
    // only check stack if there is one
           
    if (count($right)>0) {
               
    // check if we should remove a node from the stack
               
    while ($right[count($right)-1]<$row['rgt']) {
                   
    array_pop($right);
                   
    // new: also pop one off the $pathstack
                   
    array_pop($pathstack);
               }
           }

           
    // this node should be added to the last subtree in the stack
           
    $pathstack[count($pathstack)-1][] = array('title'=>$row['title']);

           
    // for the children of this node, we should add a reference to
           // this node's substree to $pathstack.
           // the last element in the last array in the stack, is the current
           // node's array. we'll add a 'subtree' element to that array, in
           // which we'll put the children of this node.
           
    $pathstack[] = &$pathstack[count($pathstack)-1]
                                     [
    count($pathstack[count($pathstack)-1])-1]
                                     [
    'subtree'];

           
    // add this node to the stack
           
    $right[] = $row['rgt'];
       }

       
    // there's only one element in the first array, that's the root node,
       // so we'll just return that first element.
       
    return $tree[0];
    }

    print_r(get_tree('Food')); 

  5. #30
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is the method I used.

    Instead of using complex DB tricks it does one query and all the logic in PHP, which seems to be very fast.

  6. #31
    ********* Member website's Avatar
    Join Date
    Oct 2002
    Location
    Iceland
    Posts
    1,238
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MattR
    Here is the method I used.

    Instead of using complex DB tricks it does one query and all the logic in PHP, which seems to be very fast.
    But if you have some enourmous trees it wont be fast since you just select everything from the table, much of something you propably wont need, right?

    And gvtulder, Thanks a lot!
    - website

  7. #32
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    website - there is only the one query in there that I can see, so regardless of the size of the table I suppose, the script it's self would proberly make up for any loss in speed as compared to other methods, no ?

    Just a though really 8)

  8. #33
    Dumb PHP codin' cat
    Join Date
    Aug 2000
    Location
    San Diego, CA
    Posts
    5,460
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is another one I wrote some time ago, so excuse any blunders I may have made at the time, basically the important parts are the way the data is laoded into an array.
    http://sitepointforum.com/showthread...ght=menusystem

  9. #34
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by website
    But if you have some enourmous trees it wont be fast since you just select everything from the table, much of something you propably wont need, right?

    And gvtulder, Thanks a lot!
    Well, it depends on what you are using it for. I am using it for navigation so all elements need to be displayed. If you are using Oracle, you have the CONNECT BY PRIOR syntax which will navigate trees for you.

    It depends on where the bottleneck is, I suppose.

  10. #35
    ********* Member website's Avatar
    Join Date
    Oct 2002
    Location
    Iceland
    Posts
    1,238
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    well, if you have tree that has many additional information (many columns in the table) and there are many rows in the table And you only need some specific part of the tree this method would be slower then other since you are extreamly much of unwanted information.

    To minimize the number of querys in your script is ofcourse good but does it reduce time to use one query and get 1000 lines/17 column table into an array or use three querys and select in all only 5 lines? I really doubt it...
    - website

  11. #36
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    freddydoesphp - had a look and looks interesting ?

    Everyone should have a look at this 8)

  12. #37
    SitePoint Zealot
    Join Date
    Dec 2001
    Location
    UK
    Posts
    105
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Thumbs up Great article - problem with adding

    Fantastic article!

    I have a question though. The method of inserting a new node in the tree does not work in all cases. I'll try to explain my problem. Here is my tree
    Code:
                  (1)L1(14)
                      |
                  (2)L2(13)
                      |
                  (3)L3(12)
                      |
            ______(4)L4(11)_____
          /           |         \
    (5)L4a(6)  (7)L4b(8)  (9)L4c(10)
    Apologies for the crudeness of the diagram. Now, if I want to add a subnode to L3, and call it L3a, then simply adding 2 to the left and right values for all nodes whose left and right values are > L3 (left value + 2), will result in the sub node appearing under L4.

    L3a's left and right values should be 12 and 13 respectively, and the L3's new right value should be 15 (its left value need not change).

    Have I misunderstood how the insert works? Here's my code in case anyone can see a mistake I have made (the db update is done through the addChild() and _updExisitingValues() methods). Thanks (again, excuse the crudeness of the code)
    PHP Code:
    <?php
      
    include('DB.php');

      class 
    tree
      
    {

          var 
    $newName;

          function 
    tree($parent
          {
              
    $dbh = new DB();
              
    $dbh->connect('****''****''****''****');

              
    $this->_parent $parent;
              
    $qry "SELECT lft, name, rgt FROM subcategory1 WHERE name = '$this->_parent'";
              
              
    $dbh->execute($qry);
              
    $this->_parentValues $dbh->fetch_assoc();   
          }      

          function 
    getChildren()
          {
              
    $dbh = new DB();
              
    $dbh->connect('****''****''****''****');

              
    $qry  "SELECT * ";
              
    $qry .= "FROM subcategory1 ";
              
    $qry .= sprintf("WHERE lft BETWEEN %s AND %s "$this->_parentValues['lft'], $this->_parentValues['rgt']);
              
    $qry .= "ORDER BY lft";  
              
              
    $dbh->execute($qry);
              return 
    $dbh->fetch_all_assoc();       
          }

          function 
    displayTree($branch
          {
              
    $stack     = array();
              
    $num_child NULL;
              
    $row       NULL;
              
              
    $node $branch[0];
              
    /* determine number of descendents main node has */
              
    $num_child['mainNode'] = ($node['rgt'] - $node['lft'] - 1) / 2;
              
    /* loop 'num of descendents' times */
              
    for($i 0$i $num_child['mainNode']; ++$i) {
                  
    /* determine number of descendants for the sub node */
                  
    $num_child['subNode'] = ($branch[$i]['rgt'] - $branch[$i]['lft'] - 1) / 2;
                  
    /* true if this sub node has no descendents */
                  
    if ($num_child['subNode'] < 1) {
                      
    /* true if the last sub node had no descendents (we don't want to pop otherwise) */
                      
    if ((($branch[$i 1]['rgt'] - $branch[$i 1]['lft'] - 1) / 2) < 1) {
                          
    /* pop the last element as this iteration contains a sibling, not a child! */
                          
    array_pop($link);                      }
                      
    /* add the sibling to the array */
                      
    $link[] = $branch[$i]['name']; 
                  } else { 
                      
    /* add child to the array */
                      
    $link[] = $branch[$i]['name'];
                  }

                  
    $path implode($link'/');
                  
    array_push($stack$path);
              }
              
    print_r($stack);
          }      


          function 
    addChild($name)
          {
              
    $dbh = new DB();
              
    $dbh->connect('****''****''****''****');

              
    $this->newNode $name;          
              
    $this->_updExistingValues();   
              
    $qry['new'] = sprintf("INSERT INTO subcategory1 VALUES (%s, '%s', %s)"$this->_parentValues['lft'] + 1$this->newNode$this->_parentValues['lft'] + 2);            
              
    $dbh->execute($qry['new']);     
              return;
          }

          function 
    _updExistingValues()
          {
              
    $dbh = new DB();
              
    $dbh->connect('localhost''torrent''test''ski_DB');
              
    $this->_parentValues['lft'] += 2;
              
    $qry['rgt'] = "UPDATE subcategory1 SET rgt = rgt + 2 WHERE rgt > {$this->_parentValues['lft']}";
              
    $qry['lft'] = "UPDATE subcategory1 SET lft = lft + 2 WHERE lft > {$this->_parentValues['lft']}";
              
    $dbh->execute($qry['rgt'], DISPLAY);
              
    $dbh->execute($qry['lft'], DISPLAY);     
              return;          
          }

      }


      
    $myTree =& new tree('link3');

    /*
      $branch = $myTree->getChildren();
      $myTree->displayTree($branch);
    */
       
      // This should add a node, link3a, to the parent node (link3 in this example)
      
    $myTree->addChild('link3a');
      
    print_r($myTree->getChildren());

    ?>

  13. #38
    SitePoint Evangelist cyngon's Avatar
    Join Date
    Aug 2001
    Location
    Livonia, MI, USA
    Posts
    513
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by torrent
    Fantastic article!
    L3a's left and right values should be 12 and 13 respectively, and the L3's new right value should be 15 (its left value need not change).
    If what you say is true, than what would have the value of 14?

    I think to do the insert you described the new right value of L3 would be 14 which follows the right += 2 formula.

    To make room you would do:

    Code:
    UPDATE table SET rgt = rgt + 2 WHERE rgt >= 12
    UPDATE table SET lft = lft + 2 WHERE lft >= 12
    And then L3a would be inserted with lft = 12 and rgt = 13.

    I think on the lines where you update the left and right values to make room for the new node you need to use >= instead of > in your WHERE clause.

  14. #39
    SitePoint Zealot
    Join Date
    Dec 2001
    Location
    UK
    Posts
    105
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the response Bryan.

    My understanding was that L3a would have a left value of 14, and a right value of 15 and L3's right value would change to 16 (sorry, not 15 as stated in my last post). I am trying to add the node as a child of L3 but not of L4. Does that make sense?

    I'll change the operand to >= and see if that makes a difference but I still think it will fall under the wrong "branch" (i.e. under L4 and not under L3). For info, and in case you would like to try this out, then here is the table schema plus my DB class. You should then be able to run the code standalone.
    Code:
    #
    # Table structure for table 'subcategory1'
    #
    
    CREATE TABLE `subcategory1` (
      `lft` int(11) default '0',
      `name` varchar(254) default NULL,
      `rgt` int(11) default NULL
    ) TYPE=MyISAM;
    
    
    
    #
    # Dumping data for table 'subcategory1'
    #
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("1", "Link1", "16");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("2", "Link2", "15");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("3", "Link3", "14");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("4", "Link4", "13");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("5", "Link4a", "6");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("7", "Link4b", "8");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("9", "Link4c", "10");
    INSERT INTO subcategory1 (lft, name, rgt) VALUES("11", "link4d", "12");
    PHP Code:
    <?php
    /**
     * Class for managing database connections
     *
     * Database class which affords easier management
     * of database connections and queries within your
     * php application, especially when utilising multiple
     * simultaneous queries and connections.
     * 
     * Public Methods:
     * DB::connect($host, $user, $pass, $db) - makes db connection
     * DB::pconnect($host, $user, $pass, $db) - makes a permanent db connection
     * DB::execute($query) - execute a SQL query
     * DB::fetch_all() - fetch results (numerical arrays within numerical array)
     * DB::fetch_all_assoc() - fetch results (assoc arrays within numerical array)
     * DB::fetch_all_obj() - fetch results (objects within numerical array)
     * DB::fetch_row() - fetch result row as numerical array
     * DB::fetch_assoc() - fetch result row as associative array
     * DB::fetch_obj() - fetch result row as an object
     * DB::db_close() - close database connection
     *
     * Examples:
     * 
     * Returning all rows as objects
     * <code>
     * $member = $myDB->fetch_all_obj();
     * 
     * // displaying results 
     * for ($i = 0, $end = sizeOf($member); $i <= $end; ++$i) {
     *     print $member[$i]->Member_Name;
     *     print "\n";
     * }
     * </code>
     *
     * Returning a single row as a numeric array and displaying
     * <code>
     * print_r($myDB->fetch_row());
     * </code>
     *
     * @author  Torrent
     * @access  public
     */
      
    class DB
      
    {
          
    /**
           * @return boolean
           * @param $host string
           * @param $user string
           * @param $pass string
           * @param $db string
           * @desc Public: Makes a database connection; returns true if connection is made, false if it fails;
           */
          
    function connect($host$user$pass$db)
          {          
              if (!
    $this->dbh = @mysql_connect($host$user$pass)) {
                  
    $this->_error();
                  return 
    false;
              }
            
              if (!@
    mysql_select_db($db)) {
                  
    $this->_error();
                  return 
    false;
              }
          }

          
    /**
           * @return boolean
           * @param $host string
           * @param $user string
           * @param $pass string
           * @param $db string
           * @desc Public: Makes a permanent database connection; returns true if connection is made, false if it fails;
           */
          
    function pconnect($host$user$pass$db)
          {          
              if (!
    $this->dbh = @mysql_connect($host$user$pass)) {
                  
    $this->_error();
                  return 
    false;
              }
            
              if (!@
    mysql_select_db($db)) {
                  
    $this->_error();
                  return 
    false;
              }
          }

          
    /**
           * @return boolean
           * @param $query string
           * @desc Public: Executes a SQL query; returns true if successful, false if not.
           */
          
    function execute($query$action null)
          {
              switch (
    $action) {
                  case 
    DISPLAY:
                      
    printf ("Executing [%s]\n"$query);
                      break;
                  default:
                      if (!
    $this->db_res = @mysql_query($query)) {
                          
    $this->_error($query);
                          return 
    false;
                      }
                      break;
              }
     
              return 
    true;
          }

          
    /**
           * @return array
           * @desc Public: Returns an array containing an array for each result row.
           */
          
    function fetch_all()
          {
              if (!
    $this->_checkResult()) die();
              
    $this->rows = array();

              while (
    $row $this->_fetch_row(DB_FETCH_NORM)) {
                  
    array_push($this->rows$row);
              }

              return 
    $this->rows;

          }

          
    /**
           * @return array
           * @desc Public: Returns an array containing an associative array for each result row.
           */
          
    function fetch_all_assoc() 
          {
              if (!
    $this->_checkResult()) die();
              
    $this->rows = array();

              if (!isset(
    $this->db_res)) {
                  
    $this->_error();
              }

              while (
    $row $this->_fetch_row(DB_FETCH_ASSOC)) {
                  
    array_push($this->rows$row);
              }

              return 
    $this->rows;
          }

          
    /**
           * @return array
           * @desc Public: Returns an array containing an object for each result row.
           */
          
    function fetch_all_obj() 
          {
              if (!
    $this->_checkResult()) die();
              
    $this->rows = array();

              while(
    $row $this->_fetch_row(DB_FETCH_OBJ)) {
                  
    array_push($this->rows$row);
              }

              return 
    $this->rows;
          }

          
    /**
           * @return integer
           * @desc Public: Returns number of rows returned from last query
           */
          
    function fetch_num_rows($res)
          {
              if (!
    $this->_checkResult()) die();
              return @
    mysql_num_rows($this->db_result);
          }

          
    /**
           * @return array
           * @desc Public: Fetch a result row as a numerical array.
           */
          
    function fetch_row()
          {

              if (!
    $this->_checkResult()) die();
              return 
    $this->_fetch_row(DB_FETCH_NORM);
          }

          
    /**
           * @return array
           * @desc Public: Fetch a result row as an associative array.
           */
          
    function fetch_assoc() 
          {
              if (!
    $this->_checkResult()) die();
              return 
    $this->_fetch_row(DB_FETCH_ASSOC);
          } 

          
    /**
           * @return array
           * @desc Public: Fetch a result row as an object.
           */
          
    function fetch_obj()
          {
              if (!
    $this->_checkResult()) die();
              return 
    $this->_fetch_row(DB_FETCH_OBJ);
          }

          
    /**
           * @return boolean
           * @desc Public: closes the database connection; returns true if successful, false if not
           */
          
    function db_close()
          {
              if (!
    mysql_close($this->dbh)) {
                  
    $this->_error();
                  return 
    false;
              }
              
              return 
    true;
          }

          
    /**
           * @return mixed
           * @param $mode string
           * @desc Private: fetches result set in chosen format (numerical or associative array, or object)
           */
          
    function _fetch_row($mode)
          {
              switch (
    $mode) {
                  case 
    DB_FETCH_NORM:
                      
    $this->row = @mysql_fetch_array($this->db_resMYSQL_NUM);
                      break;
                  case 
    DB_FETCH_ASSOC:
                      
    $this->row = @mysql_fetch_array($this->db_resMYSQL_ASSOC);
                      break;
                  case 
    DB_FETCH_OBJ:
                      
    $this->row = @mysql_fetch_object($this->db_res);
                      break;
              }
              
              return 
    $this->row;
          }

          
    /**
           * @return boolean
           * @desc Private: ensures a query result id is present; returns true if present, false if not
           */
          
    function _checkResult()
          {
              if (!isset(
    $this->db_res)) {
                  
    $this->_error();
                  return 
    false;
              }

              return 
    true;

          }

          
    /**
           * @return void
           * @desc Private: prints out the last error which occurred
           */
          
    function _error($query 'N/A')
          {
              global 
    $query;
              
    printf("ERROR! [%s] - [%s]\n"mysql_errno(), mysql_error());
              
    printf("Query [%s]\n"$query);          
          }

      } 
    // end DB class
    ?>

  15. #40
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just isolating this:
    Quote Originally Posted by torrent
    Apologies for the crudeness of the diagram. Now, if I want to add a subnode to L3, and call it L3a, then simply adding 2 to the left and right values for all nodes whose left and right values are > L3 (left value + 2), will result in the sub node appearing under L4.
    If you are adding two to the left value, then you are intending to insert the new child of L3 and sibling of 4 on the left side. In other words, L3a should have a value of 4 and 5 and you'd add two onto values greater than L3's left value. If you were inserting on the right, L3a would get values of 12 and 13 and all values starting with L3's right value would be upped by two.

    As you might have noticed, you could insert on the right side with less renumbering, but it all centers around what you intend to accomplish.

    This is how it would end up working:
    Code:
                (3) L3 (12+2)
                     |
              _________________
            /                  \
      (4) L3a (5)        (4+2) L4 (11+2)
                                |
                       ____________________
                      /         |          \
              (5+2) L4a (6+2)   |    (9+2) L4c (10+2)
                                |
                         (7+2) L4b (8+2)
    Last edited by samsm; May 20, 2003 at 09:40.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  16. #41
    SitePoint Zealot
    Join Date
    Dec 2001
    Location
    UK
    Posts
    105
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Excellent! Thanks for that, that's cleared it up in my mind. I'll make the necessary changes to the code and let you know how I get on.

  17. #42
    SitePoint Zealot
    Join Date
    Dec 2001
    Location
    UK
    Posts
    105
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yay! I got it working!

    Just need to tidy up the classes a bit and "Bob's your uncle"! Thanks for the help guys. Samsm, small gift deposited in the form of Reputation points

  18. #43
    SitePoint Member
    Join Date
    Jun 2003
    Location
    World
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about moving subtrees to another subtree??
    For example:



    If i want to do it, have i to rebuild tree(10000 nodes)??

    What method is the best to manage +10000 categories with n-sublevels??

  19. #44
    SitePoint Member
    Join Date
    Jun 2003
    Location
    World
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've read this another article:
    http://www.sqlteam.com/item.asp?ItemID=8866
    Code:
    Node ParentNode EmployeeID Depth Lineage 
    100     NULL    1001          0     / 
    101     100     1002          1     /100/ 
    102     101     1003          2     /100/101/ 
    103     102     1004          3     /100/101/102/ 
    104     102     1005          3     /100/101/102/ 
    105     102     1006          3     /100/101/102/
    And i already use this metohd for other trees. But store a "full path" of 10000 categories seems that my db will be enormous
    Last edited by Ath; Jun 7, 2003 at 16:14.

  20. #45
    ********* Member website's Avatar
    Join Date
    Oct 2002
    Location
    Iceland
    Posts
    1,238
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think the method shown in the tutorial is the best one for your case. Personally, I don't like this 'full path' thing because it has certein obvious limit, maybe it's just me, but I would always design something like this so it supports endless sub trees without any limit (except for the size on the hard drive perhaps )

    And yeah, I suppose you would need to rebuild the tree if you want to move bits of it, not sure though, I'll leave that to the experts
    - website

  21. #46
    SitePoint Member
    Join Date
    Jun 2003
    Location
    World
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for your comments website.
    First of all, i want to aply (left,right) method but i need move subtrees so this'll have a lot of problem to manage biiiig trees.

    i don't like 'full path', but this method i think the best for my case too.

    If anybody has a super wonderful method for more than 10000 nodes (and browse all at time), please tell us.

  22. #47
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, that is a limitation of nested set trees, you often have to completely recreate large parts of the table. This method definitely is for data that will be viewed much more often than it is updated.

    A formula for moving a subcat to the right would be:
    Do nothing to nodes above the top moved node.
    Subtract the amount of nodes you are moving times 2 from the nodes following the last one you wish to move but before the insert point.
    Take the number of nodes that were just moved times two and add that number onto each moving node.

    If you are moving nodes to the left you'd sort of do the reverse.

    Point is, you'll almost never change every node when you make a move... just those affected. Plus, the presumption in this method is that you need a speed boost from on you selects more than a speed boost on your inserts and updates.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  23. #48
    SitePoint Member
    Join Date
    Jun 2003
    Location
    World
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok i'll try this formula, samsm, thanks for suggestions. Like you say, i need more speed on selects.

    If i get results, i'll post here the functions.

  24. #49
    SitePoint Member
    Join Date
    Jun 2003
    Location
    World
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by samsm
    Subtract the amount of nodes you are moving times 2 from the nodes following the last one you wish to move but before the insert point.
    Ok. i can do it on my tree.

    Quote Originally Posted by samsm
    Take the number of nodes that were just moved times two and add that number onto each moving node.
    Please explain this. only need this part to move my subtree!!

  25. #50
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes! I knew I was describing that poorly when I was typing it. :-)

    For the record, I'm doing this by ear. Everything I'm suggesting is the way that I think it should work, and I'm not an expert. That said...

    Ok, let's go through this looking at your example image.

    We want to move "fruit" and all its children to under "beef". Kind of a weird example, but...

    Fruit is presently L2 R11. This means that the nodes under and including "Fruit" occupy a total of 5 nodes and 10 L or R positions. R-L+1.

    The last number in fruit is 11. The target's (Beef) first number is 13. The difference between these numbers is 2.

    Here's what must happen next. Subtact 10 from every number after "Fruit"'s highest number but before "Beef"'s highest number (14). Add 2 (the difference above) to every corner of fruit and its children. That will create the move you illustrated without rewriting the entire table.

    Does that make sense?
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •