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