phpbar.de logo

Mailinglisten-Archive

Re: Select-Alternative?
Archiv Mailingliste mysql-de

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Select-Alternative?



On Wed, Sep 13, 2000 at 09:41:43PM +0200, Jan Kunzmann wrote:
> Hi Jens,

Moin. Mein Gott, so eine ausführliche Antwort habe ich gar nicht erwartet.
Danke, danke :-))
 
> Jens Benecke wrote:
> > ich muss eine relativ grosse Abfrage über drei Tabellen realisieren, ohne
> > daß mir mein Provider wegen Ressourcen aufs Kreuz steigt. Gibt es zu
> > folgendem Code eine Alternative, die _nicht_ erst eine komplette temporäre
> > Tabelle mit allen möglichen Kombinationen anlegt und dann anfängt zu
> > filtern?
> Ja. Schon mal was von einem JOIN gehört :)) ? Steht auch im Manual,

Hm, ich bin jetzt naiverweise immer davon ausgegangen, daß das das gleiche
wäre wie untiges, weil es im Manual immer nebeneinander erwähnt wird. ;)

> sowohl im mySQL-Manual als auch in _jedem_ SQL-Manual, da es sich um die
> grundlegende Eigenschaft von Datenbanken handelt, Tabellen in Abfragen
> sinnvoll verknüpfen zu können.

Daß es Joins gibt, wußte ich. Aber dass sie hierfür viel besser geeignet
sind, nicht. Danke.
 
> Dazu ein bisschen Datenbanktheorie:
> Ein SELECT * FROM A, B macht ein karthesisches Produkt dieser beiden
> Tabellen, verknüpft also zu jeder Zeile in A alle Zeilen in B. Heraus

So sah das mir auch aus. und das ist nicht akzeptabel.

> kommt eine Tabelle mit Count(A) * Count(B) Elementen, die erst danach
> von einer eventuellen WHERE-Klausel wieder geleert wird.
> Mit einem JOIN legst du fest, dass zu jedem Datensatz in A nur die
> Zeilen aus B dazugenommen werden, bei denen eine bestimmte Spalte mit
> einem bestimmten Feld des A-Datensatzes übereinstimmt.

d.h. es wird vorher gefiltert, richtig? Genau das suche ich.
 
> > Diese Lösung kommt mir als ziemlicher Ressourcenfresser vor. Jedenfalls
> > erzeugt sie mit BIG_TABLES eine Temporärdatei von ca. 1.5GB Grösse ...
> > 
> > ---------------------------------------------------------------------------
> > SELECT h.id, h.stadt1, h.stadt2, h.stadt3, s.id, s.name, ss.id, ss.name,
> > sss.id, sss.name from h, staedte as s, staedte as ss, staedte as sss
> > WHERE (.......) AND s.id=h.stadt1 AND ss.id=h.stadt2 AND sss.id=h.stadt3
> > ORDER BY {je nachdem s.name, ss.name oder sss.name} ;
> > ---------------------------------------------------------------------------
> 
> Wie wäre es mit:
> SELECT h.id, h.stadt1, h.stadt2, h.stadt3, s1.id, s1.name, s2.id,
> s2.name, s3.id, s3.name FROM ((h INNER JOIN stadt AS s1 ON
> h.stadt1=s1.id) INNER JOIN stadt AS s2 ON h.stadt2=s2.id) INNER JOIN
> stadt AS s3 ON h.stadt3=s3.id WHERE (........) ORDER BY (....);

wenn es das gleiche Ergebnis zurückliefert, bin ich mehr als zufrieden.
 
> Bevor die WHERE-Klausel zur Anwendung kommt, enthält die temporäre
> Tabelle jetzt genauso viele Datensätze wie h zuvor, denn der JOIN geht
> jeweils auf das ID-Feld der Stadt-Tabelle (und das sollte ja nur einen
> Datensatz ergeben), also ist PRO Zeile in A mit 1 * 1 * 1 = 1 Datensätzen
> zu rechnen.

Super.
 
> Beachte, dass die INNER JOINs nur dann eine Zeile zurückliefern, wenn
> h.stadt1 und h.stadt2 und h.stadt3 gültige IDs aus der Tabelle stadt
> enthalten! Sollte in einer Zeile von h das Feld s3 einen Wert enthalten,

Das ist gewährleistet, denn die Datenbank wird mit HTML Forms gefüllt und
die Auswahlmöglichkeiten für die <SELECT> Tags kommen ebenfalls aus der DB,
zusätzlich wird nach dem Submit noch mal eine "Gegendarstellung" zur DB
gemacht.

> der nicht in stadt.id auftaucht, dann liefert die Abfrage für _diese_
> Zeile von h genau 1 * 1 * 0 = 0 Datensätze zurück. Keine Angst, die

d.h. Datensätze, die eine falsche Stadt-id enthalten, werden _garnicht_
zurückgeliefert, richtig? Damit kann ich leben.

> Um diese Problematik zu umgehen, gibt es den LEFT JOIN, den du statt dem
> INNER JOIN verwenden kannst. Im eben genannten Beispiel würde bei einem
> LEFT JOIN die Werte von s3.id und s3.name auf NULL gesetzt, daher ergäbe
> sich für diese Zeile in h wieder 1 x 1 x 1 = 1 Datensätze, und die
> resultierende Tabelle hat wieder genau h Zeilen.

Noch besser. Jetzt muss ich mir dann nur noch einfallen lassen, wie ich
dann mit solchen Datensätzen umgehe, den gerade weil sie nie auftreten
_dürften_, werden sie es garantiert tun. ;))


Nochmals vielen Dank für Deine Hilfe!
 

-- 
`Man sollte dem Verantwortlichen für ILOVEYOU alles     http://www.linuxfaq.de  
 mögliche antun, aber wahrscheinlich wird bloß       http://www.hitchhikers.de    
 seine Firma zweigeteilt." -- Usenet             http://www.pinguin.conetix.de     

PGP signature


Home | Main Index | Thread Index

php::bar PHP Wiki   -   Listenarchive