Seite 1 von 1

SQL: Selbstreferenzierende Tabelle auslesen

Verfasst: 11.05.2003 10:25
von QCO
Ich hab eine selbstreferenzierende Tabelle ala
---------------------------------------------
|| dir_id || dir_name || dir_parent ||
---------------------------------------------
1 verzeichnis1 0
2 unterverz1 1
3 test 1
.
.

Damit könnte man im Prinzip ja beliebig tiefe Strukturen bauen.
Jetzt möchte ich von einem Verzeichnis gern die übergeordneten feststellen. OK, geht mit einer rekursiven Funktion oder einer Schleife geht das. Aber dann brauch ich für jedes Verzeichnis einen Query, das können eine ganze Menge werden (und wenn man das dann noch mehrmals macht ).
Kann man auch irgendwie in SQL das Problem mit einer Abfrage erschlagen?
Oder gibt es noch einen anderen Weg?

Verfasst: 11.05.2003 11:31
von itst
Du möchtest eine Abfrage, um alle übergeordneten Verzeichnisse aller Verzeichnisse zu bekommen?

Verfasst: 11.05.2003 11:35
von QCO
wenn's geht ja...

(hallelujah, es ist doch jemand am sonntag morgen im netz)

Verfasst: 11.05.2003 11:41
von itst
Also, es mag sein, das sich ein SQL-Experte so eine Query vorstellen kann... ich denke nicht, das es geht. Vor allem dann nicht, wenn es darum geht, in einer Abfrage alle übergeordneten Verzeichnisse aller Verzeichnisse zu finden. Das sind ja teilweise ganze Bäume...

Verfasst: 11.05.2003 15:42
von Pyramide
Ich habe über so ein Problem auch schon lange gegrübelt und keine wirkliche Lösung gefunden. Das einzig mögliche ist so:

Code: Alles auswählen

SELECT d1.*, d2.* FROM dir AS d1, dir AS d2 WHERE d2.dir_id = d1.dir_parent
Das könntest du so immer weiterführen mit d3, d4 etc. Allerdings musst du für jede Ebene einen Alias erstellen und erhältst nicht automatisch den kompletten Baum.

Verfasst: 11.05.2003 18:10
von QCO
also bis jetzt hab ich es so gemacht:

Code: Alles auswählen

function get_parent_dirs($dir_id)
{
	global $db;
	$returner = array();

	$sql = 'SELECT dir_parentdir FROM ' . DIRS_TABLE . ' WHERE dir_id=' . $dir_id;
	$result = $db->sql_query($sql);
	$row  = $db->sql_fetchrow($result);

	while( $row['dir_parentdir'] != ROOT_DIR )
	{
		$sql = 'SELECT dir_id, dir_name, dir_parentdir FROM '. DIRS_TABLE . ' WHERE dir_id=' . $row['dir_parentdir'];
		$result = $db->sql_query($sql);
		$row = $db->sql_fetchrow($result);
		
		$returner[] = array( 'dir_id' => $row['dir_id'], 'dir_name' => $row['dir_name'] );
	}

	return $returner;
}
Was mir sonst noch eingefallen ist:
  • man könnte einfach mit einem riesigen Folge 'blinder' LEFT JOINs arbeiten...

    Code: Alles auswählen

    SELECT a.*, b.*, c.*, d.*, e.* FROM (((table AS a
    LEFT JOIN table b ON b.dir_parentdir=a.dir_id) 
    LEFT JOIN table c ON c.dir_parentdir=b.dir_id) 
    LEFT JOIN table d ON d.dir_parentdir=c.dir_id) 
    LEFT JOIN table d ON e.dir_parentdir=d.dir_id) 
    WHERE ...
    Nachteil: es ist plötzlich doch nicht mehr unedlich tief verschachtelbar
  • wenn man ein weiteres Datenbankfeld anlegt, in dem die Verzeichnistiefe dieses Verzeichnisses steht, kann man daraus einen beliebig großen JOIN konstruieren. Aber ist das wirklich effektiver?
Hilfe!