Mailinglisten-Archive |
Andreas Kempf aka 'amalesh' schrieb am Donnerstag, den 19. August 1999: > auf http://www.problemloeser.de/d1.htm habe ich einen artikel > gefunden, wie joins optimiert werden können. Der Artikel ist in dieser Form - ohne Bezug zu einem konkreten DBMS - sehr irreführend, denn ob bei der Ausführung der vom Ergebnis her identischen Anweisungen FROM a, b WHERE a.id=b.id ... und FROM a JOIN b ON a.id=b.id WHERE ... intern ein Unterschied gemacht wird, hängt rein von der Implementierung und evtl. Optimierungen des DBMS ab. > Überraschender weise ist das ergebnis mit mySQL jedoch anders, als > (für andere DB's?) vorhergesagt. Speziell in Bezug zu MySQL ist der Artikel sogar wertlos, da MySQL eh _nur_ die Kommaform anbietet. Der LEFT JOIN, den Du hernach verwendest, ist etwas anderes als ein normaler JOIN! > Ziel: Ich will die personenanzahl aller orte, in denen die personen > keiner niederlassung angehören. Dazu habe ich folgendes statement: > > select distinct(a.ort), count(a.id) as anzahl > from person a, > rel_niederlassung_person b > where a.id != b.person_id > group by ort > order by ort Vorbemerkung: DISTINCT(ort), ... tut etwas anderes, als Du vermutlich willst (schließe ich aus der Klammernsetzung), denn SELECT DISTINCT ... FROM bedeutet (zumindest in MySQL), daß die Ergebnistupel gesamt (also alle Ergebnisfelder als ein Wert zusammengenommen) unterschiedlich sein müssen (die Klammern um a.ort sind für MySQL hier also kein Teil von DISTINCT, sondern einfach unnötige, aber auch nicht störende Klammern um a.ort). Somit wären (Passau, 5) und (Passau, 6) mögliche Ergebnisse. In Deinem Beispiel kann aber aufgrund des GROUP BY eh kein doppelter Ort vorkommen, weshalb Du das so nicht bemerken wirst. Zur SQL-Anfrage selbst: Das funktioniert wirklich so? Kann ich nicht recht glauben ... Wenn ich das richtig verstehe, wird doch so pro Ort und pro Person dieses Ortes jede andere in der Tabelle "rel_niederlassung_person" vorkommende Person gezählt! Das ist nicht, was Du oben als Ziel angibst! Mein Lösungsvorschlag: SELECT a.ort, COUNT(*) AS anzahl FROM person AS a LEFT JOIN rel_niederlassung_person AS b ON a.id = b.id WHERE b.id IS NULL GROUP BY a.ort; Das liefert Dir pro Ort die Anzahl der Leute, die nicht in der Tabelle "rel_niederlassung_person" aufgeführt sind. Oder wolltest Du nur die Orte, wo keine Person einer Niederlassung angehört (plus die Anzahl dieser Leute)? Dann das hier: SELECT a.ort, COUNT(*) AS anzahl FROM person AS a LEFT JOIN rel_niederlassung_person AS b ON a.id = b.id GROUP BY a.ort HAVING COUNT(b.id)=0; > Tabelle person enthält ca. 4000 records. Ergebnis: 0.60 sekunden > execution time > > Wenn ich hingegen [...] > select distinct(a.ort), count(a.id) as anzahl > from person a > left join rel_niederlassung_person b > on a.id != b.person_id > group by ort > order by ort > benutze, komme ich auf 0.88 sek. execution time. Dieser Zeitunterschied dürfte einfach daher kommen, daß bei dem LEFT JOIN mehr kombinierte Datensätze entstehen, also auch mehr zu gruppieren und zählen ist. Ciao, Martin -- Martin Ramsch <m.ramsch_(at)_computer.org> <URL: http://home.pages.de/~ramsch/ > PGP KeyID=0xE8EF4F75 FiPr=52 44 5E F3 B0 B1 38 26 E4 EC 80 58 7B 31 3A D7 --- *** Abmelden von dieser Mailingliste funktioniert per E-Mail *** an mysql-de-request_(at)_lists.4t2.com mit Betreff/Subject: unsubscribe
php::bar PHP Wiki - Listenarchive