join - Abfrage

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