Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Abfragen einer Anzahl von Elementen eines Baums

Angesichts dieser Einschränkungen gibt es keine Möglichkeit. In einem solchen Fall würden Sie entweder alle abrufen den Baum und bauen Sie eine "Hügel"-Client-Seite auf oder führen Sie rekursive Abfragen durch, was im konkreten Fall am leistungsfähigsten wäre.

Mit der zusätzlichen Einschränkung, eine feste Anzahl von Hierarchieebenen zu haben , können Sie dies mit einem mehrfachen JOIN tun.

Im allgemeinen Fall gibt es mehrere Strukturmodifikationen, um die Überwindung dieser Beschränkungen zu ermöglichen. In der Praxis lockern Sie die Beschränkung „DIESES ist meine Tabellenstruktur“ und erlauben das Hinzufügen zusätzlicher Felder.

Beispielsweise könnten Sie die Knotenstruktur mit einer left_id ergänzen -Wert, und stellen Sie sicher, dass alle Knoten-IDs der Reihe nach sind, wenn Sie den Baum mit der Tiefe zuerst aufrufen:

1 --- 2 -+- 3 -+- 4
         |     |
         |     +- 5
         +- 6 --- 7

In diesem Fall würde Knoten 3 den Wert "5" speichern, Knoten 6 würde den Wert "7" speichern und Knoten 2 würde auch den Wert "7" speichern. Jeder Knoten speichert in LeftID das Maximum zwischen den LeftIDs seiner Kinder und seiner eigenen ID .

Also haben kinderlose Knoten LeftID gleich ihren IDs. Knoten 1 wird die LeftID 7 haben, da dies die LeftID von 2 ist, die sie von 6 hat.

In dieser Situation Zählen Knoten ist einfach, wenn es keine Löcher in der Sequenz gibt; alle Nachkommen eines Knotens sind diejenigen Knoten, deren ID zwischen der ID des Startknotens und seiner LeftID liegt; und Blätter werden dadurch identifiziert, dass LeftID gleich ID ist.

Also wären "alle Blätter, die von Knoten-ID 17 absteigen"

SELECT child.*FROM table AS parentJOIN table AS childON (child.id> parent.id AND child.id <=parent.leftid ) /* Descendant /WHERE child.id =child.leftid / Blatt /UND parent.id =17; / Elternteil ist 17

Diese Struktur ist umständlich beizubehalten, wenn Sie in der Lage sein wollen, Prune und Branch durchzuführen, da Sie alle Knoten zwischen dem Point of Prune bis zum Point of Branch sowie die verschobenen Knoten neu nummerieren müssen.

Eine andere Möglichkeit, wenn Sie nur am Zählen interessiert sind, besteht darin, einen Kinderzähler zu führen. Dies kann beibehalten werden, indem Sie es iterativ aktualisieren, alle Blätter auswählen und ihren Zähler auf 0 setzen (Sie identifizieren Blätter durch einen LEFT JOIN); dann aktualisieren alle Eltern mit NULL-Zählern, die Kinder mit Nicht-NULL-Zählern haben, ihre Zähler auf SUM() von Kinderzählern plus COUNT() von Kindern selbst; und fortfahren, bis die Anzahl der aktualisierten Zeilen null wird, da alle Knoten Nicht-NULL-Zähler haben. Nach einem Prune-and-Branch setzen Sie einfach alle Zähler auf NULL und wiederholen.

Dieser letzte Ansatz kostet einen reflektierenden Join für jede Hierarchieebene.