PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : MySQL: Brauche Hilfe bei JOIN


Marbleearth
2010-03-08, 10:18:33
Hallo ich habe hier 2 Tabellen. Es geht um ein Browserspiel. Tabelle user beinhaltet die Grundwerte des Nutzers. Tabelle Ausbildung die schon erspielten Ausbildungspunkte (ap_att zB Ausbildungspunkte für den Skill ATT)
Ich möchte mittels PHP eine MySQL abfrage erstellen, die die Datensätze wie folgt geordnet ausliest:

Tabelle user:
http://www.imgbox.de/users/public/thumbnails/u7545j161_t.gif (http://www.imgbox.de/?img=u7545j161.jpg)

Tabelle ausbildung:
http://www.imgbox.de/users/public/thumbnails/m37838t161_t.gif (http://www.imgbox.de/?img=m37838t161.jpg)

ausbildung.id = user.id

ich möchte die Daten nach folgender Formel geordnet auslesen:

ORDER BY ((user.points) + ((user.waffe + user.haus)*100) + ((ausbildung.ap_att + ausbildung.ap_def + ausbildung.ap_taktik)/10)) DESC

Mein Versuch war folgender:

$resultat = mysql_query ("SELECT user.id, user.name, user.points, user.waffe, user.haus, ausbildung.id, ausbildung.ap_att , ausbildung.ap_def , ausbildung.ap_taktik from user, ausbildung WHERE (user.id = ausbildung.id)
ORDER BY ((user.points) + ((user.waffe + user.haus)*100) + ((ausbildung.ap_att + ausbildung.ap_def + ausbildung.ap_taktik)/10)) DESC");

Ist das so nun richtig? Weil wenn ja wozu braucht man dann überhaupt JOINs, dann könnte man ja alles unkompliziert mit WHERE-Klauseln machen?
Ich hab schon bei Selfhtml gelesen, aber ich steig da nicht so ganz durch.
Kann mir jemand helfen?




Vielen Dank :wink:

Marscel
2010-03-08, 10:29:57
Da ich keine Spalten erkenne, die einen Bezug zwischen beiden Tabellen herstellen, nehm ich an, dass du einfach beide Tabellen zusammen in eine Ergebnismenge haben willst. Da bietet sich ein CROSS-JOIN an.

Also
SELECT [...] FROM user CROSS JOIN ausbildung ORDER BY [...]

Dann wäre die Ergebnis die Kombination jedes user-Satzes mit jedem ausbildungs-Satz.

Marbleearth
2010-03-08, 11:07:10
Da ich keine Spalten erkenne, die einen Bezug zwischen beiden Tabellen herstellen, nehm ich an, dass du einfach beide Tabellen zusammen in eine Ergebnismenge haben willst. Da bietet sich ein CROSS-JOIN an.

Also
SELECT [...] FROM user CROSS JOIN ausbildung ORDER BY [...]

Dann wäre die Ergebnis die Kombination jedes user-Satzes mit jedem ausbildungs-Satz.

naja ich hab doch geschrieben user.id = ausbildung.id oder meinst du das irgendwie anders?

Marscel
2010-03-08, 11:31:50
naja ich hab doch geschrieben user.id = ausbildung.id oder meinst du das irgendwie anders?

Ging zwischen Bild und Code-Box irgendwie unter ;) Nein, dann ist das natürlich so, wenn du keine bezugslosen Datensätze haben willst:

SELECT [...] FROM user INNER JOIN ausbildung ON (user.id = ausbildung.id) ORDER BY [...]

Marbleearth
2010-03-08, 11:40:56
Ging zwischen Bild und Code-Box irgendwie unter ;) Nein, dann ist das natürlich so, wenn du keine bezugslosen Datensätze haben willst:

SELECT [...] FROM user INNER JOIN ausbildung ON (user.id = ausbildung.id) ORDER BY [...]

okay vielen Dank. also ist es tatsächlich komplett durch meine WHERE Klausel umgehbar :biggrin:

Hardwaretoaster
2010-03-08, 18:40:58
also ist es tatsächlich komplett durch meine WHERE Klausel umgehbar
Ja, inner joins sind quasi der "Standardfall" (das sind jetzt eher praktische Prämissen denn akad. Überlegungen, also nicht auf die Goldwaage legen) und werden oft so wie du es schreibst über eine WHERE-Bedingung gelöst ohne die den inner join direkt zu schreiben.

Das lässt sich imho auch mit cross join udn Einschränkung im Where-Teil schreiben, aber das wird dann wohl schnell wenig intuitiv...

RattuS
2010-03-08, 20:46:11
Ich möchte an dieser Stelle anmerken, dass du die Relation zwischen [user] und [ausbildung] nochmal überdenken solltest. Eine [user].id kann doch n "AP"s haben oder? Folglich solltest du im Rahmen der Normalisierung folgende Relation führen (InnoDB vorausgesetzt):

[user]
id / name / pw / points / nr / geld / waffe / haus

[ap]
id / name

[user_ap]
user_id(FK) / ap_id(FK) / stufe?


Btw.: Deutsch und Englisch gemischt? :ulol:

AlecWhite
2010-03-08, 22:29:50
okay vielen Dank. also ist es tatsächlich komplett durch meine WHERE Klausel umgehbar :biggrin:
Vom Ergebnis her ja, vom Ablauf aber nein und genau hier liegt wie so oft der Hase im Pfeffer.

Mit der Where-Klausel verschenkst du zahlreiche Optimierungspotentiale des DBMS, da bei deiner Lösung erstmal die Kreuzrelation beider Relationen erzeugt wird und diese dann später gefiltert wird. Bei einem echten Join sieht das anders aus. Da wird erst gefiltert, dann die Kreuzrelation erzeugt - dadurch steigt die Performance.

Werde außerdem nie verstehen, warum Leute Joins umgehen wollen - so kompliziert sind die Dinger auch nicht.

Marbleearth
2010-03-09, 09:11:12
Ich möchte an dieser Stelle anmerken, dass du die Relation zwischen [user] und [ausbildung] nochmal überdenken solltest. Eine [user].id kann doch n "AP"s haben oder? Folglich solltest du im Rahmen der Normalisierung folgende Relation führen (InnoDB vorausgesetzt):

[user]
id / name / pw / points / nr / geld / waffe / haus

[ap]
id / name

[user_ap]
user_id(FK) / ap_id(FK) / stufe?


Btw.: Deutsch und Englisch gemischt? :ulol:

hallo es gibt noch die einzelne tabellen für ATT/DEF/etc.
irgendwo müssen ja die Grundwerte hergenommen werden. (Punktevoraussetzungen, Geldvor., Abhängigkeit von anderen Ausbildungen).

Ich sage bewusst Grundwerte, da ich aus diesen Werten mittels einer quadrat. Funktion unendlich Ausbildungsstufen berechnen kann und nicht alles in der DB vorgeben muss für jede einzelne Stufe.

Was spricht also dagegen den Fortschritt eines Unsers bezüglich Ausbildungen in einer gesamten Tabellen festzuhalten?

Ja Deu/Engl gemischt war doof hatte ich gleich am Anfang drin und ist jetzt so tief verwurzelt, dass ich es nicht mehr so leicht rausbekomme :freak:

CrazyIvan
2010-03-12, 17:38:52
Vom Ergebnis her ja, vom Ablauf aber nein und genau hier liegt wie so oft der Hase im Pfeffer.

Mit der Where-Klausel verschenkst du zahlreiche Optimierungspotentiale des DBMS, da bei deiner Lösung erstmal die Kreuzrelation beider Relationen erzeugt wird und diese dann später gefiltert wird. Bei einem echten Join sieht das anders aus. Da wird erst gefiltert, dann die Kreuzrelation erzeugt - dadurch steigt die Performance.

Werde außerdem nie verstehen, warum Leute Joins umgehen wollen - so kompliziert sind die Dinger auch nicht.
Das kann man so nicht pauschalisieren.
Beispielsweise scheint der MS SQL Server ab 2005 da sehr ausgefeilte Algorithmen zu besitzen. Der Ausführungsplan sieht da nämlich in der Regel genau gleich aus - egal, ob ich Einschränkungen in der JOIN-Klausel, der WHERE-Klausel oder sogar in einer oder mehrerer CTEs mache.
MySQL zum Beispiel ist ganz fürchterlich. Da sollte man Subselects dringendst vermeiden, weil diese für jeden DS des äusseren SELECTs durchgeführt werden. Durch Nutzung von temporären (nichtpersistenten) Tabellen kann man die Performance teilweise um mehrere 1000% erhöhen.

Hardwaretoaster
2010-03-12, 17:47:01
Mein Prof. pflegt dazu im Allgemeinen zu sagen (da schießt er gerne mal gegen MySQL...): "Bei nem gescheiten DBMS hat man sich um Performance abhängig von der Formulierung bei SQL-Statements keine Gedanken zu machen" :D

AlecWhite
2010-03-12, 21:12:37
Also das ist ja ein wenig so, als ob er sagen würde "Beim 'nem gescheiten Compiler hat man sich um die Performance abhängig von der Implementierung des Codes keine Gedanken zu machen."

sorry, aber das ist epic fail :)

Hardwaretoaster
2010-03-12, 23:17:52
Der Vergleich hinkt, wenn du die meisten verbreiteten Programmiersprachenheranziehst: Die sind nach dem imperartiven Paradigma gestrickt (da sagst du wie etwas ablaufen soll), SQL wird im Allgemeinen als deklarativ angesehen.

AlecWhite
2010-03-13, 00:23:09
Das ist richtig, nur befreit das dem Programmierer nicht von der Aufgabe darüber nachzudenken, ob seine Deklaration nicht ein wenig suboptimal ist.

Das es Aufgabe des DBMS ist die Eingabe entsprechend zu optimieren etc steht ja außer Frage....Aber man muss es dem DBMS auch nicht möglichst schwer machen :)

Wenn zwei Lösungen äquivalent sind, bevorzuge ich immer noch die, welche einfacher gestrickt ist.

Matrix316
2010-03-13, 00:27:19
Mein Prof. pflegt dazu im Allgemeinen zu sagen (da schießt er gerne mal gegen MySQL...): "Bei nem gescheiten DBMS hat man sich um Performance abhängig von der Formulierung bei SQL-Statements keine Gedanken zu machen" :D
Naja, mit Unterabfragen und geschickt gesetzten or s kannste jede Datenbank an die Wand fahren.

Hardwaretoaster
2010-03-13, 08:59:33
Naja, mit Unterabfragen und geschickt gesetzten or s kannste jede Datenbank an die Wand fahren.

Das stimmt, ist dem Prof und mir auch wohl bewusst, nur die Stoßrichtung wird bei der Überspitzung besser klar.


Das es Aufgabe des DBMS ist die Eingabe entsprechend zu optimieren etc steht ja außer Frage....Aber man muss es dem DBMS auch nicht möglichst schwer machen

Ist was dran. Und um zum Ausgangspunkt zurückzukommen: Ob ich jetzt Joins explizit oder implizit formuliere, ist geschmackssache, vom Verständnis gibt sich das nichts, da ist es dann schön, wenn die DB auch den selben Ausführungsplan dazu nimmt :)