Sql Rekursion ohne Rekursion

7

Ich habe vier Tabellen

%Vor%

Ich möchte eine Abfrage erstellen, die direkt oder indirekt alle Gruppen zurückgibt, zu denen ein Benutzer gehört. Die naheliegende Lösung besteht darin, eine Rekursion auf Anwendungsebene durchzuführen. Ich frage mich, welche Änderungen ich an meinem Datenmodell vornehmen kann, um den Datenbankzugriff zu verringern und dadurch eine bessere Leistung zu erzielen.

    
Dani Cricco 24.08.2009, 16:00
quelle

6 Antworten

16

In Oracle :

%Vor%

In SQL Server :

%Vor%

In PostgreSQL 8.4 :

%Vor%

In PostgreSQL 8.3 und darunter:

%Vor%     
Quassnoi 24.08.2009 16:17
quelle
6

There sind Wege, Rekursion in Baumhierarchieabfragen zu vermeiden (im Gegensatz zu dem, was die Leute hier gesagt haben).

Dasjenige, das ich am meisten benutzt habe, ist Nested Sets .

Wie bei allen Entscheidungen im Leben und bei der Technik müssen Kompromisse gemacht werden. Geschachtelte Sätze sind oft langsamer zu aktualisieren, aber viel schneller abzufragen. Es gibt schlaue und komplizierte Wege, die Geschwindigkeit der Aktualisierung der Hierarchie zu verbessern, aber es gibt einen weiteren Kompromiss; Leistung vs Code Komplexität.

Ein einfaches Beispiel für einen verschachtelten Satz ...

Baumansicht:

%Vor%

Verschachtelte Mengenrepräsentation

%Vor%

Sie sollten den Artikel lesen, den ich verlinkt habe , um dies vollständig zu verstehen, aber Ich werde versuchen, eine kurze Erklärung zu geben.

Ein Element ist ein Mitglied eines anderen Elements, wenn (der "lft" (Links) -Wert des Kindes größer ist als der "ltf" -Wert des Elternteils) UND (der "rgt" -Wert des Kindes ist kleiner als der "rgt" -Wert des Elterns)

"Flash" ist daher ein Mitglied von "MP3 PLAYERS", "Portable Electronics" und "Electronics"

Oder, converleyy, die Mitglieder von "Portable Electronics" sind:
- MP3-Player - Flash-Spiele - CD-Spieler
- 2-Wege-Radios

Joe Celko hat ein ganzes Buch über "Bäume und Hierarchien in SQL". Es gibt mehr Optionen als Sie denken, aber viele Kompromisse zu machen.

Hinweis: Sag niemals, dass etwas nicht gemacht werden kann. Einige Mofo werden auftauchen, um dir das zu zeigen.

    
MatBailie 24.08.2009 16:49
quelle
1
___ qstntxt ___

Ich habe vier Tabellen

%Vor%

Ich möchte eine Abfrage erstellen, die direkt oder indirekt alle Gruppen zurückgibt, zu denen ein Benutzer gehört. Die naheliegende Lösung besteht darin, eine Rekursion auf Anwendungsebene durchzuführen. Ich frage mich, welche Änderungen ich an meinem Datenmodell vornehmen kann, um den Datenbankzugriff zu verringern und dadurch eine bessere Leistung zu erzielen.

    
___ antwort1323293 ___

Können Sie den Unterschied zwischen einer Entität und einem Benutzer klären? Ansonsten sehen Ihre Tabellen OK aus. Sie machen eine Annahme, dass es eine Viele-zu-Viele-Beziehung zwischen Gruppen und Entitäten gibt.

Verwenden Sie auf jeden Fall bei Standard-SQL diese Abfrage:

%Vor%

Dies gibt Ihnen eine Liste von Namen und Gruppen-IDs, ein Paar pro Zeile. Wenn eine Entität Mitglied mehrerer Gruppen ist, wird die Entität mehrmals aufgeführt.

Wenn Sie sich fragen, warum es keinen JOIN für die groups-Tabelle gibt, liegt das daran, dass keine Daten aus der groups-Tabelle vorhanden sind, die nicht bereits in der Tabelle group_members enthalten sind. Wenn Sie beispielsweise einen Gruppennamen in die Gruppentabelle aufgenommen haben und Sie möchten, dass dieser Gruppenname angezeigt wird, müssen Sie auch Gruppen beitreten.

Einige SQL-Varianten haben Befehle in Bezug auf das Reporting. Sie würden Ihnen erlauben, mehrere Gruppen in derselben Zeile als eine einzelne Entität aufzulisten. Aber es ist kein Standard und würde nicht auf allen Plattformen funktionieren.

    
___ antwort1323299 ___

Wenn Sie eine wirklich theoretisch unendliche Verschachtelungsebene wünschen, dann ist die Rekursion die einzige Option, die eine vernünftige Version von SQL ausschließt. Wenn Sie es einschränken möchten, gibt es eine Reihe anderer Optionen.

Sehen Sie sich diese Frage an.

    
___ answer1323510 ___

There sind Wege, Rekursion in Baumhierarchieabfragen zu vermeiden (im Gegensatz zu dem, was die Leute hier gesagt haben).

Dasjenige, das ich am meisten benutzt habe, ist Nested Sets .

Wie bei allen Entscheidungen im Leben und bei der Technik müssen Kompromisse gemacht werden. Geschachtelte Sätze sind oft langsamer zu aktualisieren, aber viel schneller abzufragen. Es gibt schlaue und komplizierte Wege, die Geschwindigkeit der Aktualisierung der Hierarchie zu verbessern, aber es gibt einen weiteren Kompromiss; Leistung vs Code Komplexität.

Ein einfaches Beispiel für einen verschachtelten Satz ...

Baumansicht:

%Vor%

Verschachtelte Mengenrepräsentation

%Vor%

Sie sollten den Artikel lesen, den ich verlinkt habe , um dies vollständig zu verstehen, aber Ich werde versuchen, eine kurze Erklärung zu geben.

Ein Element ist ein Mitglied eines anderen Elements, wenn (der "lft" (Links) -Wert des Kindes größer ist als der "ltf" -Wert des Elternteils) UND (der "rgt" -Wert des Kindes ist kleiner als der "rgt" -Wert des Elterns)

"Flash" ist daher ein Mitglied von "MP3 PLAYERS", "Portable Electronics" und "Electronics"

Oder, converleyy, die Mitglieder von "Portable Electronics" sind:
- MP3-Player - Flash-Spiele - CD-Spieler
- 2-Wege-Radios

Joe Celko hat ein ganzes Buch über "Bäume und Hierarchien in SQL". Es gibt mehr Optionen als Sie denken, aber viele Kompromisse zu machen.

Hinweis: Sag niemals, dass etwas nicht gemacht werden kann. Einige Mofo werden auftauchen, um dir das zu zeigen.

    
___ answer1323715 ___

Ich glaube nicht, dass hier eine Rekursion notwendig ist, da die Lösung, die von Barry-Brown angeboten wird, angemessen erscheint. Wenn Sie eine Gruppe benötigen, um Mitglied einer Gruppe zu sein, dann funktioniert die Baumdurchsuchungsmethode, die von Dems angeboten wird, gut. Einfügungen, Löschungen und Aktualisierungen sind mit diesem Schema ziemlich einfach und das Abrufen der gesamten Hierarchie erfolgt mit einer einzigen Auswahl.

Ich würde vorschlagen, ein Feld "parent_id" in die Tabelle "group_members" aufzunehmen (unter der Annahme, dass dies der Punkt ist, an dem Ihre rekursive Beziehung auftritt). In einem Navigationseditor habe ich eine Knotentabelle wie folgt erstellt:

%Vor%

Mein Editor erstellt hierarchisch verwandte Objekte aus einer C # -Knotenklasse

%Vor%

Die Nodes-Eigenschaft enthält eine Liste von untergeordneten Knoten. Wenn die Business-Schicht die Hierarchie lädt, werden die übergeordneten / untergeordneten Beziehungen berichtigt. Wenn der Nav-Editor speichert, setze ich rekursiv den linken und rechten Eigenschaftswert und speichere dann in der Datenbank. Dadurch kann ich die Daten in der richtigen Reihenfolge ausgeben, was bedeutet, dass ich Eltern- / Kind-Referenzen während des Abrufs festlegen kann, anstatt einen zweiten Durchlauf durchführen zu müssen. Dies bedeutet auch, dass alles andere, was die Hierarchie anzeigen muss (z. B. ein Bericht), die Knotenliste problemlos in der richtigen Reihenfolge anzeigen kann.

Ohne ein parent_id-Feld können Sie mit

eine Brotkrumenspur zum aktuellen Knoten abrufen %Vor%

Dabei ist @id die ID des Knotens, an dem Sie interessiert sind.

Das ist ziemlich offensichtlich, aber es bezieht sich auf Elemente wie die Mitgliedschaft in verschachtelten Gruppen, die möglicherweise nicht offensichtlich sind, und wie andere gesagt haben, beseitigt die Notwendigkeit, rekursives SQL zu verlangsamen.

    
___ tag123postgresql ___ PostgreSQL ist ein Open-Source-Objekt-relationales Datenbankmanagementsystem (ORDBMS), das für alle wichtigen Plattformen einschließlich Linux, UNIX, Windows und OS X verfügbar ist. Bitte geben Sie Ihre genaue Version von Postgres an, wenn Sie Fragen stellen. Fragen zur Administration oder erweiterten Funktionen richten Sie am besten auf dba.stackexchange.com. ___ answer1323302 ___

Sie können Folgendes tun:

  • Verwenden Sie die Konstrukte , um START / CONNECT BY PRIOR zu starten.
  • Erstellen Sie eine PL / SQL-Funktion.
___ tag123sql ___ Structured Query Language (SQL) ist eine Sprache für die Abfrage von Datenbanken. Fragen sollten Codebeispiele, Tabellenstruktur, Beispieldaten und ein Tag für die verwendete DBMS-Implementierung (z. B. MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 usw.) enthalten. Wenn sich Ihre Frage nur auf ein bestimmtes DBMS bezieht (verwendet bestimmte Erweiterungen / Funktionen), verwenden Sie stattdessen das Tag des DBMS. Antworten auf mit SQL gekennzeichnete Fragen sollten den ISO / IEC-Standard SQL verwenden. ___ tag123datamodeling ___ Datenmodellierungsfragen beziehen sich auf die Techniken, die zum Sammeln und Analysieren von Datenanforderungen verwendet werden, die zur Unterstützung von Datenoperationen in Programmen und Systemen benötigt werden. ___ qstnhdr ___ Sql Rekursion ohne Rekursion ___ answer1323338 ___

In %code% :

%Vor%

In %code% :

%Vor%

In %code% :

%Vor%

In %code% und darunter:

%Vor%     
___
Barry Brown 24.08.2009 16:09
quelle
0
___ qstntxt ___

Ich habe vier Tabellen

%Vor%

Ich möchte eine Abfrage erstellen, die direkt oder indirekt alle Gruppen zurückgibt, zu denen ein Benutzer gehört. Die naheliegende Lösung besteht darin, eine Rekursion auf Anwendungsebene durchzuführen. Ich frage mich, welche Änderungen ich an meinem Datenmodell vornehmen kann, um den Datenbankzugriff zu verringern und dadurch eine bessere Leistung zu erzielen.

    
___ antwort1323293 ___

Können Sie den Unterschied zwischen einer Entität und einem Benutzer klären? Ansonsten sehen Ihre Tabellen OK aus. Sie machen eine Annahme, dass es eine Viele-zu-Viele-Beziehung zwischen Gruppen und Entitäten gibt.

Verwenden Sie auf jeden Fall bei Standard-SQL diese Abfrage:

%Vor%

Dies gibt Ihnen eine Liste von Namen und Gruppen-IDs, ein Paar pro Zeile. Wenn eine Entität Mitglied mehrerer Gruppen ist, wird die Entität mehrmals aufgeführt.

Wenn Sie sich fragen, warum es keinen JOIN für die groups-Tabelle gibt, liegt das daran, dass keine Daten aus der groups-Tabelle vorhanden sind, die nicht bereits in der Tabelle group_members enthalten sind. Wenn Sie beispielsweise einen Gruppennamen in die Gruppentabelle aufgenommen haben und Sie möchten, dass dieser Gruppenname angezeigt wird, müssen Sie auch Gruppen beitreten.

Einige SQL-Varianten haben Befehle in Bezug auf das Reporting. Sie würden Ihnen erlauben, mehrere Gruppen in derselben Zeile als eine einzelne Entität aufzulisten. Aber es ist kein Standard und würde nicht auf allen Plattformen funktionieren.

    
___ antwort1323299 ___

Wenn Sie eine wirklich theoretisch unendliche Verschachtelungsebene wünschen, dann ist die Rekursion die einzige Option, die eine vernünftige Version von SQL ausschließt. Wenn Sie es einschränken möchten, gibt es eine Reihe anderer Optionen.

Sehen Sie sich diese Frage an.

    
___ answer1323510 ___

There sind Wege, Rekursion in Baumhierarchieabfragen zu vermeiden (im Gegensatz zu dem, was die Leute hier gesagt haben).

Dasjenige, das ich am meisten benutzt habe, ist Nested Sets .

Wie bei allen Entscheidungen im Leben und bei der Technik müssen Kompromisse gemacht werden. Geschachtelte Sätze sind oft langsamer zu aktualisieren, aber viel schneller abzufragen. Es gibt schlaue und komplizierte Wege, die Geschwindigkeit der Aktualisierung der Hierarchie zu verbessern, aber es gibt einen weiteren Kompromiss; Leistung vs Code Komplexität.

Ein einfaches Beispiel für einen verschachtelten Satz ...

Baumansicht:

%Vor%

Verschachtelte Mengenrepräsentation

%Vor%

Sie sollten den Artikel lesen, den ich verlinkt habe , um dies vollständig zu verstehen, aber Ich werde versuchen, eine kurze Erklärung zu geben.

Ein Element ist ein Mitglied eines anderen Elements, wenn (der "lft" (Links) -Wert des Kindes größer ist als der "ltf" -Wert des Elternteils) UND (der "rgt" -Wert des Kindes ist kleiner als der "rgt" -Wert des Elterns)

"Flash" ist daher ein Mitglied von "MP3 PLAYERS", "Portable Electronics" und "Electronics"

Oder, converleyy, die Mitglieder von "Portable Electronics" sind:
- MP3-Player - Flash-Spiele - CD-Spieler
- 2-Wege-Radios

Joe Celko hat ein ganzes Buch über "Bäume und Hierarchien in SQL". Es gibt mehr Optionen als Sie denken, aber viele Kompromisse zu machen.

Hinweis: Sag niemals, dass etwas nicht gemacht werden kann. Einige Mofo werden auftauchen, um dir das zu zeigen.

    
___ answer1323715 ___

Ich glaube nicht, dass hier eine Rekursion notwendig ist, da die Lösung, die von Barry-Brown angeboten wird, angemessen erscheint. Wenn Sie eine Gruppe benötigen, um Mitglied einer Gruppe zu sein, dann funktioniert die Baumdurchsuchungsmethode, die von Dems angeboten wird, gut. Einfügungen, Löschungen und Aktualisierungen sind mit diesem Schema ziemlich einfach und das Abrufen der gesamten Hierarchie erfolgt mit einer einzigen Auswahl.

Ich würde vorschlagen, ein Feld "parent_id" in die Tabelle "group_members" aufzunehmen (unter der Annahme, dass dies der Punkt ist, an dem Ihre rekursive Beziehung auftritt). In einem Navigationseditor habe ich eine Knotentabelle wie folgt erstellt:

%Vor%

Mein Editor erstellt hierarchisch verwandte Objekte aus einer C # -Knotenklasse

%Vor%

Die Nodes-Eigenschaft enthält eine Liste von untergeordneten Knoten. Wenn die Business-Schicht die Hierarchie lädt, werden die übergeordneten / untergeordneten Beziehungen berichtigt. Wenn der Nav-Editor speichert, setze ich rekursiv den linken und rechten Eigenschaftswert und speichere dann in der Datenbank. Dadurch kann ich die Daten in der richtigen Reihenfolge ausgeben, was bedeutet, dass ich Eltern- / Kind-Referenzen während des Abrufs festlegen kann, anstatt einen zweiten Durchlauf durchführen zu müssen. Dies bedeutet auch, dass alles andere, was die Hierarchie anzeigen muss (z. B. ein Bericht), die Knotenliste problemlos in der richtigen Reihenfolge anzeigen kann.

Ohne ein parent_id-Feld können Sie mit

eine Brotkrumenspur zum aktuellen Knoten abrufen %Vor%

Dabei ist @id die ID des Knotens, an dem Sie interessiert sind.

Das ist ziemlich offensichtlich, aber es bezieht sich auf Elemente wie die Mitgliedschaft in verschachtelten Gruppen, die möglicherweise nicht offensichtlich sind, und wie andere gesagt haben, beseitigt die Notwendigkeit, rekursives SQL zu verlangsamen.

    
___ tag123postgresql ___ PostgreSQL ist ein Open-Source-Objekt-relationales Datenbankmanagementsystem (ORDBMS), das für alle wichtigen Plattformen einschließlich Linux, UNIX, Windows und OS X verfügbar ist. Bitte geben Sie Ihre genaue Version von Postgres an, wenn Sie Fragen stellen. Fragen zur Administration oder erweiterten Funktionen richten Sie am besten auf dba.stackexchange.com. ___ answer1323302 ___

Sie können Folgendes tun:

  • Verwenden Sie die Konstrukte , um START / CONNECT BY PRIOR zu starten.
  • Erstellen Sie eine PL / SQL-Funktion.
___ tag123sql ___ Structured Query Language (SQL) ist eine Sprache für die Abfrage von Datenbanken. Fragen sollten Codebeispiele, Tabellenstruktur, Beispieldaten und ein Tag für die verwendete DBMS-Implementierung (z. B. MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 usw.) enthalten. Wenn sich Ihre Frage nur auf ein bestimmtes DBMS bezieht (verwendet bestimmte Erweiterungen / Funktionen), verwenden Sie stattdessen das Tag des DBMS. Antworten auf mit SQL gekennzeichnete Fragen sollten den ISO / IEC-Standard SQL verwenden. ___ tag123datamodeling ___ Datenmodellierungsfragen beziehen sich auf die Techniken, die zum Sammeln und Analysieren von Datenanforderungen verwendet werden, die zur Unterstützung von Datenoperationen in Programmen und Systemen benötigt werden. ___ qstnhdr ___ Sql Rekursion ohne Rekursion ___ answer1323338 ___

In %code% :

%Vor%

In %code% :

%Vor%

In %code% :

%Vor%

In %code% und darunter:

%Vor%     
___
Adam Robinson 24.08.2009 16:10
quelle
0

Sie können Folgendes tun:

  • Verwenden Sie die Konstrukte , um START / CONNECT BY PRIOR zu starten.
  • Erstellen Sie eine PL / SQL-Funktion.
ATorras 24.08.2009 16:11
quelle
0

Ich glaube nicht, dass hier eine Rekursion notwendig ist, da die Lösung, die von Barry-Brown angeboten wird, angemessen erscheint. Wenn Sie eine Gruppe benötigen, um Mitglied einer Gruppe zu sein, dann funktioniert die Baumdurchsuchungsmethode, die von Dems angeboten wird, gut. Einfügungen, Löschungen und Aktualisierungen sind mit diesem Schema ziemlich einfach und das Abrufen der gesamten Hierarchie erfolgt mit einer einzigen Auswahl.

Ich würde vorschlagen, ein Feld "parent_id" in die Tabelle "group_members" aufzunehmen (unter der Annahme, dass dies der Punkt ist, an dem Ihre rekursive Beziehung auftritt). In einem Navigationseditor habe ich eine Knotentabelle wie folgt erstellt:

%Vor%

Mein Editor erstellt hierarchisch verwandte Objekte aus einer C # -Knotenklasse

%Vor%

Die Nodes-Eigenschaft enthält eine Liste von untergeordneten Knoten. Wenn die Business-Schicht die Hierarchie lädt, werden die übergeordneten / untergeordneten Beziehungen berichtigt. Wenn der Nav-Editor speichert, setze ich rekursiv den linken und rechten Eigenschaftswert und speichere dann in der Datenbank. Dadurch kann ich die Daten in der richtigen Reihenfolge ausgeben, was bedeutet, dass ich Eltern- / Kind-Referenzen während des Abrufs festlegen kann, anstatt einen zweiten Durchlauf durchführen zu müssen. Dies bedeutet auch, dass alles andere, was die Hierarchie anzeigen muss (z. B. ein Bericht), die Knotenliste problemlos in der richtigen Reihenfolge anzeigen kann.

Ohne ein parent_id-Feld können Sie mit

eine Brotkrumenspur zum aktuellen Knoten abrufen %Vor%

Dabei ist @id die ID des Knotens, an dem Sie interessiert sind.

Das ist ziemlich offensichtlich, aber es bezieht sich auf Elemente wie die Mitgliedschaft in verschachtelten Gruppen, die möglicherweise nicht offensichtlich sind, und wie andere gesagt haben, beseitigt die Notwendigkeit, rekursives SQL zu verlangsamen.

    
David Lively 24.08.2009 17:33
quelle

Tags und Links