join - Abfrage
am 30.05.2006 09:24:13 von Daniel Schmidt
Hallo Newsgroup,
ich möchte folgende Abfrage realisieren:
es sollen alle Werte aus einer Tabelle abgefragt werden, die in der
2ten Tabelle nicht vorkommen.
SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE a.name!=b.name
bringt nicht das gewünschte Ergebnis.
Wie sieht die richtige Lösung aus?
Grüße Daniel
Re: join - Abfrage
am 30.05.2006 09:55:48 von Tobias Kutzler
Hallo Daniel,
Daniel Schmidt schrieb:
> es sollen alle Werte aus einer Tabelle abgefragt werden, die in der
> 2ten Tabelle nicht vorkommen.
>
> SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE a.name!=b.name
Das funktioniert prinzipiell nicht. Du musst hier den Negationsoperator
NOT verwenden:
SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE NOT a.name=b.name
> bringt nicht das gewünschte Ergebnis.
>
> Wie sieht die richtige Lösung aus?
Welche MySQL Version verwendest Du? Ab - ich glaube 4.1 - werden
Sub-Queries unterstützt, die man hier wunderbar einsetzen könnte:
SELECT a.name, a.datum FROM tab1 WHERE NOT a.name IN (SELECT b.name FROM
tab2)
Ciao,
Tobias
Re: join - Abfrage
am 30.05.2006 10:06:30 von Thomas Rachel
Daniel Schmidt wrote:
> es sollen alle Werte aus einer Tabelle abgefragt werden, die in der
> 2ten Tabelle nicht vorkommen.
>
> SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE a.name!=b.name
>
> bringt nicht das gewünschte Ergebnis.
>
> Wie sieht die richtige Lösung aus?
Du suchst den LEFT JOIN.
SELECT a.name, a.datum FROM tab1 a LEFT JOIN tab2 b USING (name) WHERE
a.name IS NOT NULL AND b.name IS NULL
verbindet a mit allen passenden Zeilen aus b, sofern vorhanden - falls nicht
vorhanden, wird stattdessen eine Komplett-NULL-Zeile in b angenommen.
Die Bedingung "a.name IS NOT NULL" kannst Du weglassen, wenn b.name eh nie
NULLwerden kann oder aber eine Spalte aus b prüfen, die normalerweise nicht
NULL werden kann.
(Aber wo war da jetzt der PHP-Bezug? de.comp.datenbanken.mysql wäre
passender gewesen (so es sich denn überhaupt um MySQL handelt, andernfalls
de.comp.datenbanken.misc).)
HTH,
Thomas
Re: join - Abfrage
am 30.05.2006 10:19:10 von Helmut Chang
Daniel Schmidt schrieb:
> es sollen alle Werte aus einer Tabelle abgefragt werden, die in der
> 2ten Tabelle nicht vorkommen.
>
> SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE a.name!=b.name
>
> bringt nicht das gewünschte Ergebnis.
>
> Wie sieht die richtige Lösung aus?
In de.comp.datenbanken.misc zu posten beispielsweise. Weil kein
PHP-Problem vorhanden ist.
Einfache Möglichkeit:
SELECT a.name, a.datum
FROM tab1 a
LEFT OUTER JOIN tab2 b ON a.name = b.name
WHERE b.name IS NULL
Crosspost und Follow-Up d.c.d.misc
Gruss, Helmut
Re: join - Abfrage
am 30.05.2006 10:59:49 von Alex Hepp
> Das funktioniert prinzipiell nicht. Du musst hier den Negationsoperator
> NOT verwenden:
>
> SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE NOT a.name=b.name
>
Das wäre mir aber neu, dass ein != nicht funktioniert, denn laut SQL
ANSI müsste man eher <> verwenden... in manchen (den meisten)
SQL-Versionen gibt es auch !=, und mysql kennt eben auch den
vorangestellten NOT Operator.
http://www.w3schools.com/sql/sql_where.asp
>> Wie sieht die richtige Lösung aus?
>
> Welche MySQL Version verwendest Du? Ab - ich glaube 4.1 - werden
> Sub-Queries unterstützt, die man hier wunderbar einsetzen könnte:
>
> SELECT a.name, a.datum FROM tab1 WHERE NOT a.name IN (SELECT b.name FROM
> tab2)
Ein Subquery funktioniert hier zwar, aber auch nicht so, wie es der OP
gewünscht hatte... ausserdem ist es im Vergleich zu dem, wie man es
lösen sollte, nämlich mit einem simplen LEFT JOIN, unglaublich uneffizient.
Ein LEFT JOIN würde in mysql bspwse so ausschauen:
SELECT a.name, a.datum
from tab1 a LEFT JOIN tab2 ON a.name = b.name
WHERE b.name IS NULL
viel spass...
grüße
alex hepp
Re: join - Abfrage
am 30.05.2006 12:10:01 von Tobias Kutzler
Alex Hepp schrieb:
>> Das funktioniert prinzipiell nicht. Du musst hier den
>> Negationsoperator NOT verwenden:
>>
>> SELECT a.name, a.datum FROM tab1 a, tab2 b WHERE NOT a.name=b.name
>>
>
> Das wäre mir aber neu, dass ein != nicht funktioniert, denn laut SQL
> ANSI müsste man eher <> verwenden... in manchen (den meisten)
> SQL-Versionen gibt es auch !=, und mysql kennt eben auch den
> vorangestellten NOT Operator.
>
> http://www.w3schools.com/sql/sql_where.asp
Ok, wieder was gelernt. Aber nicht in Deinem angegebenen Link (der gilt
für allgemeines SQL) sondern hier:
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators. html
>>> Wie sieht die richtige Lösung aus?
>>
>> Welche MySQL Version verwendest Du? Ab - ich glaube 4.1 - werden
>> Sub-Queries unterstützt, die man hier wunderbar einsetzen könnte:
>>
>> SELECT a.name, a.datum FROM tab1 WHERE NOT a.name IN (SELECT b.name
>> FROM tab2)
>
> Ein Subquery funktioniert hier zwar, aber auch nicht so, wie es der OP
> gewünscht hatte... ausserdem ist es im Vergleich zu dem, wie man es
> lösen sollte, nämlich mit einem simplen LEFT JOIN, unglaublich uneffizient.
Also ich denke schon, dass mein Vorschlag das gleiche Ergebnis liefert.
Und was die Effizienz angeht: Ein cleverer interner Optimierer setzt ein
Statement intern sowieso so um, dass er es am schnellsten ausführen kann.
> Ein LEFT JOIN würde in mysql bspwse so ausschauen:
>
> SELECT a.name, a.datum
> from tab1 a LEFT JOIN tab2 ON a.name = b.name
> WHERE b.name IS NULL
Ich habe mal beide Versionen mit großen Datenmengen getestet. Bei den
Ausführungsgeschwindigkeiten habe ich festgestellt, dass mal die eine
und mal die andere Version schneller ist. Im Endeffekt nehmen sie sich
also nix.
Ciao,
Tobias
Re: join - Abfrage
am 30.05.2006 13:46:00 von Alex Hepp
Tobias Kutzler schrieb:
> Ok, wieder was gelernt. Aber nicht in Deinem angegebenen Link (der gilt
> für allgemeines SQL) sondern hier:
> http://dev.mysql.com/doc/refman/5.0/en/comparison-operators. html
>
Wir befinden uns hier in einer NG, bei der es generell um PHP in
Verbindung mit Datenbanken geht, da dass aber nichts darüber aussagt,
mit welcher DB, heisst das, dass es eigentlich erstmal um Standard ANSI
SQL gehen sollte... Und genau das wird dort erklärt.
Natürlich kann man für die einzelnen Datenbanken dann immer die besseren
oder für einen selbst schöneren Lösungen nehmen, und dann eben auch
die Referenzen dort.
>>>> Wie sieht die richtige Lösung aus?
> Also ich denke schon, dass mein Vorschlag das gleiche Ergebnis liefert.
> Und was die Effizienz angeht: Ein cleverer interner Optimierer setzt ein
> Statement intern sowieso so um, dass er es am schnellsten ausführen kann.
Das habe ich ja nicht bestritten, und wenn Du mir beweist, oder mir ein
DB-Admin erzählt, dass der interne Optimierer von MySQL, oder wem auch
immer ein Statement mit Subquery in einen JOIN baut, und umgekehrt, je
nachdem, was evtl. effizienter ist, dann staune ich Bauklötze... Aber
würde mich freuen, weil ich wieder mehr weiss...
Vielleicht erfahren wir ja hier mehr:
http://dev.mysql.com/doc/refman/5.0/en/left-join-optimizatio n.html
Aber zumindest ist mir während der Lektüre dieser Seite mal wieder
aufgefallen, dass man sich viel anlesen muss, um tatsächlich effiziente
und leicht optimierbare Statements zu schreiben. Wie gut, dass es da
Profis gibt ;)
> Ich habe mal beide Versionen mit großen Datenmengen getestet. Bei den
> Ausführungsgeschwindigkeiten habe ich festgestellt, dass mal die eine
> und mal die andere Version schneller ist. Im Endeffekt nehmen sie sich
> also nix.
Es geht nicht nur um grosse Datenmengen (btw: was sind für Dich grosse
Mengen?), sondern auch um Tabellenlayout, sowie Indexing.
Aber wenn Du unbedingt Subqueries verwenden willst, probier doch auch
noch das hier aus:
SELECT DISTINCT a.name,a.datum FROM tab1 a
WHERE NOT EXISTS (SELECT b.name FROM tab2 b
WHERE b.name = a.name);
Ist das schneller???
lg. alex