Rekursives Auslesen php &mysql

Daniel Steffen novinet

Angesehenes Mitglied
Hallo,

ich habe ein Problem:

Ich habe Bildergallerien, die wiederum Untergallerien enthalten können (unbegrenzt). Jede Gallerie kann auch Bilder haben.

So, nun habe ich z.B. folgende Struktur

KFZ
- Audi
#bild von audi allgemein
- A4
# bild von a4
# bild2 von a4
# bild 3 von a4
- A6
# bild von a6
- BMW
.....


Ich habe dafür 2 Tabellen, eine mit den Galerien, wobei ich zum Titel noch eine mother_id speichere, also wer ist die mutter-gallerie, sowie das level (wobei das jetzt nicht wichtig ist).

ich habe noch eine tabelle "bilder", in der jeweils die gallerie-id referernziert ist.

Kann mir jemand helfen - wie bekomme ich jetzt eine rekursive funktion, die mir zu jeder gallerie die darin enthaltenen Bilder berechnet? Wichtig ist, dass natürlich die nächsthöhere Gallerie auch alle bilder enthalten muss, die in den Untergallerien vorhanden sind.

Das ganze entspricht also dem Zählen von objekten innerhalb von ordnern wie man es von windows aus kennt.

Kann mir jemand helfen? Ich habe immer Funktonen zusammenbekommen, die ähnlich dem waren was ich brauchte, aber nie korrekt. Seh den Wald wohl vor lauter Bäumen auch nicht mehr.

Danke für eure Hilfe!

Gruß, Daniel (der, der keine rekursiven Funktionen mag)
 
QUOTE (Daniel Steffen - ehemals Cieslar @ Mi 17.12.2008, 22:41) KFZ
- Audi
#bild von audi allgemein
- A4
# bild von a4
# bild2 von a4
# bild 3 von a4
- A6
# bild von a6
- BMW
.....


Ich habe dafür 2 Tabellen, eine mit den Galerien, wobei ich zum Titel noch eine mother_id speichere, also wer ist die mutter-gallerie, sowie das level (wobei das jetzt nicht wichtig ist).


"mother_id"

KrümelNavigation (das Wort hab ich aus einem Google SEO PDF)

KFZ
KFZ » Audi
KFZ » Audi » A4
KFZ » Audi » A6
KFZ » BMW
KFZ » BMW » 3er
KFZ » BMW » 5er
KFZ » BMW » 7er


Recursion (freihand geschrieben)

CODE
$viewID = $_GET['gal'];

while( $viewID )
{
$query = " SELECT * FROM galerie";
$query .= " WHERE id IN ($viewID)";
echo('<hr>'.$query.'<hr>');
$result = mysql_query($query) or die('<hr>'.$query.'<hr>'.mysql_error());
while( $line= mysql_fetch_array($result, MYSQL_ASSOC))
{
// hier die Ausgabe der Galrey
}

$nextID= ' ,';
$query = " SELECT * FROM galerie";
$query .= " WHERE mother_id IN ($viewID)";
$query .= " GROUP BY mother_id";
echo('<hr>'.$query.'<hr>');
$result = mysql_query($query) or die('<hr>'.$query.'<hr>'.mysql_error());
while( $line= mysql_fetch_array($result, MYSQL_ASSOC))
{
if ( !strpos( $nextID , ','.$line['id'].',' ) $nextID .= $line['id'].',';
}
$nextID = str_replace( ',' , ' ' , $nextID );
$nextID = trim( $nextID );
$nextID = str_replace( ' ' , ',' , $nextID );
$viewID = $nextID;
}



Also, Die ID der aktuellen ... in der motherID der Anderen suchen ....



//EDIT

ein wenig geschickter wäre ....
... die "Childs" bei der "mother" aufzulisten ... dann hätte man die Liste schon bei der Abfrage der "Mother" und müßte die Kinder nicht nach der Mutter absuchen

das ist zwar kontraproduktiv bezüglich "Normalisierung" ... aber, es spart eben einen Arbeitsschritt
 
Wenn die Anzahl der Ebenen unbegrenzt ist, kann MySQL alleine nicht mithalten. D.h. Du must Dir eine PHP-Funktion bzw. Schleife bauen, die jeweils die Anzahl Bilder im aktuellen Verzeichnis zählt, die nächst tieferen Ebenen ausliest und dann dort wieder zählt, usw.

Ich hoffe, Du willst so eine Funktion nicht bei jedem Aufruf laufen lassen, da jeder Zugriff auf die Datenbank relativ zeitaufwendig ist und je nach Anzahl Ebenen können da schon einige Abfragen zustande kommen.
 
QUOTE ein wenig geschickter wäre ....
... die "Childs" bei der "mother" aufzulisten ... dann hätte man die Liste schon bei der Abfrage der "Mother" und müßte die Kinder nicht nach der Mutter absuchen



Oder Du speicherst anstatt oder zusätzlich zur Mother-ID den Pfad, sprich "Main-ID/Child-ID/Child-ID/..."
 
@800XE

Ist das nicht ne "iterative Lösung" (while ruft quasi nach Schleife, also nach einem iterativen Algorithmus)? Rekursion sehe ich da keine
blink.gif
 
Beschäftige mich trad schon mit Nested Sets... aber bis dahin - hat hier keiner mal sowas gemacht? Hat keiner ne Lösung?

Gruß, Daniel (der, der nested sets auch nicht mag)
 
@Daniel (der, der immer in der 3. Person von sich spricht)
laugh.gif


Wie schon gesagt, wenn Du keine Schleife mit x DB-Abfragen willst, musst du den Pfad ("Main-ID/Sub-ID/Sub-Sub-ID/usw.") komplett speichern. Dann kannst Du die Anzahl der Bilder mit nur einer MySQL-Abfrage abrufen.
 
Das mit der dritten Person ist der Pluralis Majestatis
ph34r.gif


Hmm... ich steh hier weiter auf dem Schlauch, wie kann ich dann das total berechnen?

Gruß, Daniel (der, der von sich in der dritten Person spricht)
 
QUOTE (Chrischii @ Do 18.12.2008, 20:40) @800XE

Ist das nicht ne "iterative Lösung" (while ruft quasi nach Schleife, also nach einem iterativen Algorithmus)? Rekursion sehe ich da keine
blink.gif


http://de.wikipedia.org/wiki/Iterative_Programmierung

Eine Normale Schleife, die wird innerhalb des Schleifencodes nicht verändert ... auser das der Zähler zählt

bei meienr Schleife wird aber die Schleifenbedingung geändert ....
.... pack die Schleife in eine Funktion und ruf am Ende der Funktion die Funktion selbst auf ....


Bei einer Normalen Schleife, kannst du bei bzw vor dem Ersten Durchlauf sagen wie oft sie durchlaufen wird ...
... bei einer Rekursion geht diese Vorhersage nicht
bei meiner "Schleife" geht diese Vorhersage auch nicht
Fazit: meine iteration ist eine Rekursion


Gruß
Andy 800XE Zmuda
 
QUOTE Hmm... ich steh hier weiter auf dem Schlauch, wie kann ich dann das total berechnen?



Na so:


CODE SELECT
 COUNT(*)
FROM
 bilder b,
 verzeichnisse vz
WHERE
 b.vzid = vz.id AND
 vz.path LIKE CONCAT((
   SELECT
     path
   FROM
     verzeichnisse
   WHERE
     id = 'verzeichnis_id'
   LIMIT 1),'/%')

(ungetestet)
 
Interessant, die Methode mit der doppelten Nummerierung (links und rechts) kannte ich noch nicht. Das Problem dabei: Mit jedem neuen Verzeichnis muss man die Nummerierung auch bei anderen Verzeichnissen revidieren. Ich bleibe weiterhin dabei, dass die Pfad-Lösung die schnellste und einfachste ist, solange die anzahl Ebenen nicht begrenzt ist.

Gerade auch, wenn man irgendwann einmal ein Verzeichnis verschieben will. Mit dieser doppeleten Nummerierung würde das extrem schwierig und komplex. Mit der Pfad-Lösung hingegen ist auch dies relativ einfach zu bewerkstelligen.
 
QUOTE (Marcus Tullius @ Do 18.12.2008, 23:19)
QUOTE Hmm... ich steh hier weiter auf dem Schlauch, wie kann ich dann das total berechnen?



Na so:


CODE SELECT
COUNT(*)
FROM
bilder b,
verzeichnisse vz
WHERE
b.vzid = vz.id AND
vz.path LIKE CONCAT((
SELECT
path
FROM
verzeichnisse
WHERE
id = 'verzeichnis_id'
LIMIT 1),'%')

(ungetestet)

Ist da jetzt Rekursion oder iteration ... also "Schleife" drin?

der "concat" baut einen String auf für die "UnterGalery(en)" ...
... aber, doch nur die genau darunter, wenn die Untergall noch eine Untergal ...
... dann sind die nicht geConcatet?
 
Weder noch. Das ist eine simple MySQL-Abfrage. Wenn zu jedem Verzeichnis der Pfad gespeichert wird, kann man mit
CODE LIKE 'pfad/%'

ganz einfach alle Unterordner lokalisieren. Mit CONCAT wird nur der String "pfad/%" zusammengebaut (und die Sub-Query ist drin, da ich davon ausgehe, dass von dem Verzeichnis nur die ID, nicht aber der Pfad, bekannt ist).
 
Da die Unterverzeichnisse ja unbegrenzt sein sollen, würde ich hier auf nested sets zurück greifen.
Sich da einzulesen bedarf ein wenig Arbeit/Zeit, lohnt sich aber wirklich.
 
QUOTE (Marcus Tullius @ Fr 19.12.2008, 17:06) Weder noch. Das ist eine simple MySQL-Abfrage. Wenn zu jedem Verzeichnis der Pfad gespeichert wird, kann man mit

CODE LIKE 'pfad/%'

ganz einfach alle Unterordner lokalisieren. Mit CONCAT wird nur der String "pfad/%" zusammengebaut (und die Sub-Query ist drin, da ich davon ausgehe, dass von dem Verzeichnis nur die ID, nicht aber der Pfad, bekannt ist).

"ganz einfach"

ich arbeite mit $path
und wenn jetzt ein Request auf /kfz/Audi/A4/ kommt
dann ... mach ich einen strTok und zerbrößel das und bau mir 3 Strings auf
/kfz/
/kfz/Audi/
/kfz/Audi/A4/
mach einen SELECT mit OR und hab die "darüber"

hir will einer "nach unten" ... eventuell "mehrfach"

id path
1 kfz
2 Audi
3 BMW
4 A4
5 A8

dein Query nat ein "WHERE id" er will ja nach unten ... und nun sucht man die ID in "mother" ... muß aber die gefundenen IDs wiederum in "mother" suchen .... was bei dir doch nicht geschieht?


CODE
WHERE
b.vzid = vz.id AND
vz.path LIKE CONCAT((

mag noch stimmen

aber

CODE
WHERE
id = 'verzeichnis_id'


macht doch das gewünschte "go deeper" kaput
Es ist doch "immer" die ID der aktuelle vieGall ... niemals die der gefundenen unterGalls
?

Gruß
Andy 800XE Zmuda


PS
der SQL ist komplizierter wie die die ich so nutze ....
... vielleicht hast du recht ... aber ich denke(sonst würd ich das ja nicht schreiben) mein EInwand ist berechtigt
 
Ergänzung

Die ID im 2ten WHERE die ist mir da einfach falsch

aber, sorum ....


CODE
mainSELECT

subSELECT id
WHERE aktuellCaturl LIKE Caturl


also, die IDs von URLs sammeln, die "Links" wie die aktuelle + noch etwas länger
 
Zurück
Oben