2011-01-14 10 views
2

Lassen Sie uns sagen, dass ich eine Tabelle namens my_table haben, die wie folgt aussieht:Wie kann ich alle untergeordneten Elemente aus einer übergeordneten Zeile in derselben Tabelle abrufen?

id  | name     | parent_id 
1  | Row 1     | NULL 
2  | Row 2     | NULL 
3  | Row 3     | 1 
4  | Row 4     | 1 
5  | Row 5     | NULL 
6  | Row 6     | NULL 
7  | Row 7     | 8 
8  | Row 8     | NULL 
9  | Row 9     | 4 
10  | Row 10     | 4 

Grundsätzlich möchte ich meine letzte Array in PHP sehen wie folgt aus:

Array 
(
    [0] => Array 
     (
      [name] => Row 1 
      [children] => Array 
       (
        [0] => Array 
         (
          [name] => Row 3 
          [children] => 
         ) 

        [1] => Array 
         (
          [name] => Row 4 
          [children] => Array 
           (
            [0] => Array 
             (
              [name] => Row 9 
              [children] => 
             ) 

            [1] => Array 
             (
              [name] => Row 10 
              [children] => 
             ) 

           ) 

         ) 

       ) 

     ) 

    [1] => Array 
     (
      [name] => Row 2 
      [children] => 
     ) 

    [2] => Array 
     (
      [name] => Row 5 
      [children] => 
     ) 

    [3] => Array 
     (
      [name] => Row 6 
      [children] => 
     ) 

    [4] => Array 
     (
      [name] => Row 8 
      [children] => Array 
       (
        [0] => Array 
         (
          [name] => Row 7 
          [children] => 
         ) 

       ) 

     ) 

) 

Also, ich will alles bekommen der Zeilen, in denen parent_id den Wert null hat, suchen Sie anschließend alle verschachtelten untergeordneten Elemente rekursiv.

Jetzt ist hier der Teil, den ich Mühe, mich mit:

Wie kann dies mit 1 Aufruf der Datenbank durchgeführt werden?

Ich bin sicher, dass ich es mit einer einfachen Select-Anweisung tun könnte und dann PHP das Array so aussehen lassen, aber ich hoffe, dass dies mit einer Art von db Beitritt oder etwas ähnliches getan werden kann.

Antwort

1

Mir ist keine Möglichkeit bekannt, ein solches Array von einem einzigen Datenbankaufruf zu erhalten. Eine mysql-SQL-Abfrage gibt ein tabellenartiges Dataset zurück, das immer spaltenbasiert ist. Daher lautet die Antwort Sie können nicht.

Es ist jedoch möglich, sehr intelligent baumbasierte Abfragen zu machen. Eine sehr interessante Lektüre dazu finden Sie unter here.

Auf anderen Systemen als mysql, Common table expressions könnte erreichen, was Sie wollen.

Aber immer noch keine solche Array out of the Box.

0

AFAIK ist es nicht möglich. Es sei denn, Sie schreiben eine gespeicherte Prozedur, um den Job auszuführen.

0

Ich weiß nicht, MySQL, aber in SQL Server (und ich glaube, das ist ANSI-SQL) wird dies mit einem CTE (Common Table Expression) durchgeführt, die diese Form annimmt:

WITH MyCTE 
(
    -- Non-recursive anchor query 
    UNION ALL 
    -- Recursive portion that typically JOINs MyCTE to some other table 
) 
SELECT * FROM MyCTE; 
+0

rekursive Abfragen auf Oracle und aktuelle PostgreSQl sind als gut, aber nicht MySQL. – regilero

0

Problem hier ist, dass IDs nicht in der Reihenfolge gespeichert werden, in der Sie Ihren Baum durchlaufen würden. Wenn Sie dieses Problem beheben, indem Sie Ihren Baum einmal erstellen und dann alle Knoten zurück in die andere Tabelle kopieren und die ID entsprechend der Reihenfolge zuweisen, in der die Knoten durchlaufen werden, können Sie den Baum das nächste Mal durch einfaches Scannen der Ergebnisse füllen der Select-Anweisung wie

SELECT * FROM my_table ORDER BY Id.

Diese Lösung funktioniert nicht, wenn sich der Baum häufig ändert, weil die Tabelle neu generiert werden muss. Dies kann dadurch gelöst werden, dass die IDs zunächst um eine große Zahl (etwa 1000) erhöht werden, so dass nicht jedes Mal eine erneute Nummerierung erforderlich ist, da Sie eine neue Knoten-ID aus der Lücke zuweisen können. Die Verwendung von Brüchen für Schlüssel funktioniert auch gut, wenn die Höhe des Baumes klein ist.

0

Einfachster Weg ist es einfach in PHP zu tun. Ich musste etwas Ähnliches in Symfony machen, aber es sollte leicht zu lesen und anzupassen sein. Beginnen Sie mit einem Array aus den Tabellenzeilen.

public function executeGetTree(sfWebRequest $request) 
    { 
    $rows = Doctrine_Core::getTable('TreeNode')->findAll(); 
    $treeNodes = $rows->toArray(); 

    //set up new array to store children for each parent node 
    $nodesContainer = array(); 
    foreach ($treeNodes as $node){ 
     $parentId = $node['parent_id']; 
     //if node has no parent, it is a root node 
     $nodesContainer[isset($parentId)? $parentId : 'root'][] = $node; 
    } 

    $tree = array(); 
    //recursively get descendents for each root node 
    foreach($nodesContainer['root'] as $rootNode) 
    { 
     $tree[] = $this->getChildren($nodesContainer, array($rootNode)); 
    } 

    print_r($tree); 

    return sfView::NONE; 
    } 

    private function getChildren(&$container, $parentNode){ 
     $children = array(); 
     foreach ($parentNode as $node){ 
      if(isset($container[$node['id']])){ 
      $node['children'] = $this->getChildren($container, $container[$node['id']]); 
      } 
      $children[] = $node; 
     } 
     return $children; 
    } 
0

ich das bin der Hoffnung, kann mit irgendeiner Art von Phantasie db Füge- oder so etwas getan werden.

Sie sollten überlegen, wie unmöglich das klingt. Betrachten Sie nur eine Verzweigung in der Struktur, von 1 -> 4 -> 9 Wie würden Sie die Beziehung in einer einzelnen Zeile in der MySql-Ergebnis oder jedes DBMS visualisieren.

Die einzige vernünftige Option, die ich für hierarchisches Ergebnis in Betracht ziehen kann, ist XML, aber Sie wollen nicht dorthin gehen, da es viel besser in PHP auf der Basis record.parent-Struktur statt XML-Analyse durchgeführt werden kann.

0

Vielleicht so etwas wie, fügen Sie Ebenen entsprechend:

SELECT 
    d1.*, 
    d2.`name` AS '2nd Level', 
    d3.`name` AS 'Top Level' 
    FROM `my_table` AS d1 
    LEFT JOIN `my_table` AS d2 ON d1.parent_id=d2.id 
    LEFT JOIN `my_table` AS d3 ON d2.parent_id=d3.id 
Verwandte Themen