php / Mysql najlepsza struktura drzewa

Muszę zbudować drzewo, które będzie zawierało około 300 węzłów wewnątrz niego. Drzewo nie ma ograniczeń głębokości. Więc może mieć 3 lub 15 poziomów. Każdy węzeł może mieć nieograniczoną liczbę dzieci.

Priorytetem jest jak najszybsze uzyskanie pełnego drzewa / poddrzewa, ale muszę też czasami dodawać węzły lub przenosić węzły, ale nie tak często.

Chcę znać najlepszy sposób przechowywania drzewa w bazie danych i najlepszy sposób pobierania danych, jeśli to możliwe, w php.

Author: OMG Ponies, 2011-05-07

3 answers

Możesz użyć zagnieżdżonego modelu zestawu, ponieważ daje bardzo wydajne zapytania. Sprawdź Zarządzanie danymi hierarchicznymi w MySQL i przeczytaj sekcję o nazwie zagnieżdżony model zestawu.

Jeśli używasz doktryny podobnej do ORM, to zawiera zagnieżdżone możliwości zestawu .

Niektórym może być trudno zrozumieć zagnieżdżone pojęcia zbioru left i right. odkryłem, że używanie tych liczb jako analogii do numerów linii znaczników open/close w dokumencie XML ludzie łatwiej go zrozumieć.

Na przykład, weźmy przykład danych z linku MySQL powyżej:

+-------------+----------------------+-----+-----+
| category_id | name                 | lft | rgt |
+-------------+----------------------+-----+-----+
|           1 | ELECTRONICS          |   1 |  20 |
|           2 | TELEVISIONS          |   2 |   9 |
|           3 | TUBE                 |   3 |   4 |
|           4 | LCD                  |   5 |   6 |
|           5 | PLASMA               |   7 |   8 |
|           6 | PORTABLE ELECTRONICS |  10 |  19 |
|           7 | MP3 PLAYERS          |  11 |  14 |
|           8 | FLASH                |  12 |  13 |
|           9 | CD PLAYERS           |  15 |  16 |
|          10 | 2 WAY RADIOS         |  17 |  18 |
+-------------+----------------------+-----+-----+

Jeśli weźmiesz lft, RGT pola i używać ich jako numerów linii dla dokumentu XML, otrzymasz:

1. <electronics>
2.    <televisions>
3.        <tube>
4.        </tube>
5.        <lcd>
6.        </lcd>
7.        <plasma>  
8.        </plasma> 
9.     </televisions>
10.    <portable electronics>
11.        <mp3 players>
12.            <flash>
13.            </flash>
14.        </mp3 players>
15.        <cd players>
16.        </cd players>
17.        <2 way radios>
18.        </2 way radios>
19.    </portable electronics>
20. </electronics>

Zobaczenie go w ten sposób może znacznie ułatwić niektórym wizualizację wynikowej hierarchii zagnieżdżonych zestawów. Wyjaśnia również, dlaczego takie podejście poprawia wydajność, ponieważ umożliwia wybór całych węzłów bez potrzeba wielu zapytań lub łączy.

 71
Author: webbiedave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-15 20:44:12

Świetny artykuł na ten temat: Zarządzanie danymi hierarchicznymi w MySQL . Używałem przez długi czas.

Jeśli masz jakieś matematyczne zdolności, możesz naprawdę zrozumieć, dlaczego jest tak wielki!

 7
Author: Marcin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-05 16:50:51
            <?php

            $host = "localhost";
            //Database user name.   
            $login = "root";
            //Database Password.
            $dbpass = "";
            $dbname = "abc";
            $PDO = new PDO("mysql:host=localhost;dbname=$dbname", "$login", "$dbpass");
            $rows = array();
            $sql = 'SELECT id, parent_id, name FROM employee';
            $query = $PDO->prepare($sql);
            $query->execute();
            $rows = array();

                if (!$query)
                {
                    $error = 'Error fetching page structure, for nav menu generation.';
                    exit();
                }

            while($row = $query->fetch(PDO::FETCH_ASSOC)){
                if( strcasecmp($row['parent_id'],'null') === 0 || empty($row['parent_id']) ) {
                     $row['parent_id'] = null;
                }

                $rows[] = $row;
            }


            // covert raw result set to tree
            $menu = convertAdjacencyListToTree(null,$rows,'id','parent_id','links');
            // echo '<pre>',print_r($menu),'</pre>';

            // display menu
            echo themeMenu($menu,1);

            /*
            * ------------------------------------------------------------------------------------
            * Utility functions
            * ------------------------------------------------------------------------------------
            */

            /*
            * Convert adjacency list to hierarchical tree
            *
            * @param value of root level parent most likely null or 0
            * @param array result
            * @param str name of primary key column
            * @param str name of parent_id column - most likely parent_id
            * @param str name of index that children will reside ie. children, etc
            * @return array tree
            */
            function convertAdjacencyListToTree($intParentId,&$arrRows,$strIdField,$strParentsIdField,$strNameResolution) {

                $arrChildren = array();

                for($i=0;$i<count($arrRows);$i++) {
                    if($intParentId === $arrRows[$i][$strParentsIdField]) {
                        $arrChildren = array_merge($arrChildren,array_splice($arrRows,$i--,1));
                    }
                }

                $intChildren = count($arrChildren);
                if($intChildren != 0) {
                    for($i=0;$i<$intChildren;$i++) {
                        $arrChildren[$i][$strNameResolution] = convertAdjacencyListToTree($arrChildren[$i][$strIdField],$arrRows,$strIdField,$strParentsIdField,$strNameResolution);
                    }
                }

                return $arrChildren;

            }

            /*
            * Theme menu
            *
            * @param array menu
            * @param runner (depth)
            * @return str themed menu
            */
            function themeMenu($menu,$runner) {

                $out = '';

                if(empty($menu)) {
                    return $out;
                }

                $out.='<ul>';
                foreach($menu as $link) {
                    $out.= sprintf(
                        '<li class="depth-%u">%s%s</li>'
                        ,$runner
                        ,$link['name']
                        ,themeMenu($link['links'],($runner+1))
                    );
                }

                $out.='</ul>';
                return $out;

            }

            ?>
 0
Author: Gaurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-08 12:12:19