Rekursives Selbst tritt bei

15

Ich habe eine commentsTabelle, die vereinfacht werden kann:

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

where parent_idist nullwertfähig, kann jedoch ein Schlüssel für den übergeordneten Kommentar sein.


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

Josh
quelle

Antworten:

16

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

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

Wenn Sie eine Problemumgehung benötigen, finden Sie hier einen dynamischen (und damit möglicherweise gefährlichen) Trick: /programming/8104187/mysql-hierarchical-queries

Weitere Informationen zum Speichern hierarchischer Daten mit anderen Modellen als mit einer Adjacency-Liste (dh der übergeordneten Spalte) finden Sie hier: /programming/192220/what-is-the-most-efficient- eleganter-weg-einen-flachen-tisch-in-einen-baum-zu-parsen /

Viel Glück!

Valmoer
quelle
Ich frage mich, wie diese Lösung in Ihrem zweiten Link gefährlich sein kann. Kannst du es erklären? Ansonsten herzlich willkommen auf der Seite!
Dezso
3
@dezso: Quassnoi, der Verfasser der Abfrage, selbst. " * Es ist nicht upgrade-sicher *, weil MySQL das Verhalten von Sitzungsvariablen nicht klar definiert. Es ist jedoch die einzige Möglichkeit, Adjazenzlisten rechtzeitig abzufragen ." Dangerous war vielleicht ein zu starkes Wort ( möglicherweise instabil ?), Aber ich ziehe es vor, auf Nummer sicher zu gehen (außerdem kenne ich mich in Oracle besser aus als in MySQL, deshalb wollte ich besonders vorsichtig sein). Danke übrigens für die Begrüßung! Ich war lange Zeit ein Lauerer im SE-Netzwerk, und ich entschied, dass es Zeit war, etwas zurückzuzahlen.
Valmoer
2
Die WITH [RECURSIVE] -Syntax wird jetzt von MySQL 8.0 unterstützt. dev.mysql.com/doc/refman/8.0/en/with.html
ClearCrescendo
6

Bei diesem Tabellendesign handelt es sich um ein SQL-Antipattern "Naive trees", wie es von Bill Karwin beschrieben wurde ( siehe 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 deren RECURSIVE-Modifikator) verwenden, die in anderen RDBMS vorhanden sind.

Was Ihnen noch bleibt, ist:

  • Verwenden Sie eine alternative Implementierung der hierarchischen Datenstruktur (Antworten auf diese Frage sind möglicherweise eine gute Referenz).
  • Erstellen Sie Self-Join-Abfragen mit einem Tiefenlimit. Für Tiefe = 5 könnten Sie etwas in den Zeilen von verwenden:

    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).

redguy
quelle
2
Ich bin hier nicht einverstanden mit Bill Karwin. Das Adjazenzmodell ist kein Anti-Pattern. Mit einem modernen DBMS, das rekursive Abfragen unterstützt (Oracle unterstützt dies seit über 20 Jahren), lässt sich ein solches Modell sehr effizient abrufen und aktualisieren.
a_horse_with_no_name
5

MySQL unterstützt keine rekursiven Abfragen wie die, die Sie benötigen.

Vor einiger Zeit habe ich gespeicherte Prozeduren geschrieben, die das Modell dafür darstellen.

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

Kurz gesagt, die gespeicherten Prozeduren, die ich erstellt habe, führen eine Vorbestellung der Baumdurchquerung mithilfe der Warteschlangenverarbeitung durch

  • GetParentIDByID
  • GetAncestry
  • GetFamilyTree

Eltern für alle Kinder (wie GetFamilyTree Stored Procedure)

  • SCHRITT 01) Beginnen Sie mit einem parent_idin einer Warteschlange
  • SCHRITT 02) Den nächsten parent_idals den Strom aus der Warteschlange nehmen
  • SCHRITT 03) Alle idWerte einreihen , die den Strom habenparent_id
  • SCHRITT 04) Den Kommentar ausdrucken oder einsammeln
  • SCHRITT 05) Wenn die Warteschlange nicht leer ist, gehe zu STEP02
  • SCHRITT 06) Fertig !!!

Child to all Parent (wie GetAncestry Stored Procedure)

  • SCHRITT 01) Beginnen Sie mit einem idin einer Warteschlange
  • SCHRITT 02) Den nächsten idals den Strom aus der Warteschlange nehmen
  • SCHRITT 03) Den parent_idWert des Stroms in eine Warteschlange einreihenid
  • SCHRITT 04) Den Kommentar ausdrucken oder einsammeln
  • SCHRITT 05) Wenn die Warteschlange nicht leer ist, gehe zu STEP02
  • SCHRITT 06) Fertig !!!

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

Versuche es !!!

RolandoMySQLDBA
quelle
2
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

Praveen Prasannan
quelle