it-swarm.com.de

Rekursive Selbstverbindungen

Ich habe eine comments Tabelle, die bis dahin vereinfacht werden kann:

comments
=======
id
user_id
text
parent_id

wo parent_id ist nullwertfähig, kann aber ein Schlüssel für den übergeordneten Kommentar sein.


Wie kann ich nun alle Nachkommen eines bestimmten Kommentars select?
Die Kommentare können mehrere Ebenen tiefer sein ...

15
Josh

Hierarchische Abfragen , da diese rekursiven Abfragen bekannt sind, werden für MySQL nicht unterstützt.

Sie werden jedoch unter anderem in Oracle, Microsoft SQL Server, DB2 und PostgreSQL unterstützt.

Wenn Sie eine Problemumgehung benötigen, finden Sie hier einen dynamischen (und damit potenziell gefährlichen) Trick: https://stackoverflow.com/questions/8104187/mysql-hierarchical-queries

Sie können auch eine Diskussion darüber finden, wie hierarchische Daten mit anderen Modellen als mit einer Adjazenzliste gespeichert werden (dh mit Parent = Spalte) hier: https://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way-to-parse-a-flat-table-into-a-tree /

Viel Glück!

16
Valmoer

Dieses Tabellendesign ist ein SQL-Antimuster "Naive Bäume", wie von Bill Karwin beschrieben (Blick von Folie 48 in seiner Präsentation SQL Antipatterns Strike Back ). Das Problem bei diesem Entwurf ist insbesondere die Schwierigkeit, alle Nachkommen (oder Eltern) eines Knotens zu erhalten. Da Sie MySQL verwenden, können Sie keine allgemeinen Tabellenausdrücke (die WITH-Anweisung und den RECURSIVE-Modifikator) verwenden, die in anderen RDBMS vorhanden sind.

Was Ihnen bleibt, ist:

  • verwenden Sie eine alternative Implementierung der hierarchischen Datenstruktur (Antworten auf diese Frage könnten eine gute Referenz dazu sein.)
  • erstellen Sie Self-Join-Abfragen mit einer Tiefenbegrenzung. Für Tiefe = 5 könnten Sie etwas in den Zeilen verwenden von:

    SELECT *
    FROM comments AS c1
      JOIN comments AS c2 ON (c2.parent_id = c1.id)
      JOIN comments AS c3 ON (c3.parent_id = c2.id)
      JOIN comments AS c4 ON (c4.parent_id = c3.id)
      JOIN comments AS c5 ON (c5.parent_id = c4.id)
    
  • verwenden Sie ein RDBMS, das WITH RECURSIVE unterstützt (obwohl dies für die meisten Menschen höchstwahrscheinlich keine Option ist).

7
redguy

MySQL unterstützt keine rekursiven Abfragen wie die von Ihnen benötigte.

Was ich vor einiger Zeit getan habe, war, gespeicherte Prozeduren zu schreiben, die das Modell dafür liefern.

Anstatt das Rad neu zu erfinden, werde ich Ihnen die Links zu meinen früheren Beiträgen dazu geben:

Kurz gesagt, die von mir erstellten gespeicherten Prozeduren führen das Durchlaufen von Bäumen mithilfe der Warteschlangenverarbeitung vor

  • GetParentIDByID
  • GetAncestry
  • GetFamilyTree

Eltern aller Kinder (wie GetFamilyTree Stored Procedure)

  • SCHRITT01) Beginnen Sie mit einem parent_id In einer Warteschlange
  • SCHRITT02) Den nächsten parent_id Als aktuellen aus der Warteschlange entfernen
  • SCHRITT03) Alle id -Werte mit dem aktuellen parent_id In die Warteschlange stellen.
  • SCHRITT 04) Drucken oder sammeln Sie den Kommentar
  • SCHRITT 05) Wenn die Warteschlange nicht leer ist, gehe zu STEP02
  • SCHRITT 06) Du bist fertig !!!

Kind für alle Eltern (wie GetAncestry Stored Procedure)

  • SCHRITT01) Beginnen Sie mit einem id in einer Warteschlange
  • SCHRITT02) Deaktivieren Sie das nächste id als das aktuelle
  • SCHRITT03) Den parent_id - Wert des aktuellen id in die Warteschlange stellen
  • SCHRITT 04) Drucken oder sammeln Sie den Kommentar
  • SCHRITT 05) Wenn die Warteschlange nicht leer ist, gehe zu STEP02
  • SCHRITT 06) Du bist fertig !!!

Bitte schauen Sie sich die gespeicherten Prozeduren in meinen anderen Beiträgen an, um die Implementierung zu sehen.

Versuche es !!!

5
RolandoMySQLDBA
SELECT  group_concat(@id :=
        (
        SELECT  id
        FROM    comments
        WHERE   parent_id = @id
        )) AS comment
FROM    (
        SELECT  @id := 1
        ) vars
STRAIGHT_JOIN
        comments
WHERE   @id IS NOT NULL

Geige

2