Datenbankabfrage dieser Art moeglich?

Datenbankabfrage dieser Art moeglich?

am 15.08.2006 21:27:32 von Hannes

Hallo,

ich stehe gerade vor einem Problem, bei dem ich nicht so recht weiter
weiss.
Zur Zeit wollte ich mir ein Adressbuch programmieren, stehe aber vor
folgendem Problem.
Die Datenbank besteht (vereinfacht) aus zwei Tabellen. Eine Tabelle
contact (ID, name, first, ...) und einer Tabelle email (ID, contact_id,
address).
Nun ist es moeglich, dass ein Kontakt eine bis unendl. viele Adressen,
aber auch keine eMailadresse haben kann.
Die Relation zwischen den beiden Tabellen besteht aufgrund (contact.id
<--> email.contact_id).

Probleme habe ich nun, eine Anfrage an die MySQL DB zu formulieren, die
folgendes macht:
Es sollen alle Namen aus contact ausgegeben mit der moeglicherweise
vorhanden eMail Adresse, aber jeder Name nur einmal (erste auftauchende
eMail zu Name reicht).

Wenn ich nun schreibe:
SELECT email.email_address, contact.id, contact.name,
d_contact.first_name
FROM contact, email
WHERE ad_email.person_id = ad_contact.id
GROUP BY name, first_name";
dann bekomme ich alle Name nur einmal ausgegeben, aber Eintraege ohne
eMail werden nicht ausgegeben (fuer Namen ohne email gibt es ja auch
keinen id Eintrag in der eMail Tabelle)

Wenn ich es nun wie folgt formuliere:
SELECT email.email_address, contact.id, contact.name,
d_contact.first_name
FROM contact, email
WHERE ad_email.person_id = ad_contact.id
OR ad_email.person_id is NULL";
GROUP BY name, first_name";
dann bekomme ich alle Name und eMail Adressen ausgegeben, auch die
Namen ohne eMail, aber es werden alle Eintraege ausgegeben
(Doppeltnennungen).

Daher meine Frage: Ist diese Problem ueberhaupt mit einer Anfrage
moeglich zu loesen?
Gibt es in SQL einen geeigneten Befehl, der dieses Problem loesen?

Vielen Dank fuer Eure Tipps!

Viele Gruesse,
Hannes

Re: Datenbankabfrage dieser Art moeglich?

am 15.08.2006 21:58:53 von Thomas Rachel

Hannes wrote:

Nachname wäre gern gesehen.


> Es sollen alle Namen aus contact ausgegeben mit der moeglicherweise
> vorhanden eMail Adresse, aber jeder Name nur einmal (erste auftauchende
> eMail zu Name reicht).
>
> Wenn ich nun schreibe:
> SELECT email.email_address, contact.id, contact.name,
> d_contact.first_name
> FROM contact, email
> WHERE ad_email.person_id = ad_contact.id
> GROUP BY name, first_name";
> dann bekomme ich alle Name nur einmal ausgegeben, aber Eintraege ohne
> eMail werden nicht ausgegeben (fuer Namen ohne email gibt es ja auch
> keinen id Eintrag in der eMail Tabelle)

Eben. Das ",", mit dem Du die Tabellen verknüpfst, ist (quasi) äquivalent zu
einem CROSS JOIN. Die Verknüpfungsbedingung schreibst Du dann in den
WHERE-Teil.

Das ist eher ungünstig; für diesen Zweck gibt es extra die Konstrukte USING
und ON. Lies Dir am besten nochmal den entsprechenden Abschnitt im Handbuch
durch (Stichwort JOIN).

Was Du des weiteren suchst, ist der LEFT JOIN.


Außerdem paßt Dein Query oben nicht - eigentlich sollte hier ein Fehler
auftreten, weil Du unter FROM die Tabellen contact und email stehen hast,
unter WHERE aber ad_email und ad_contact, in der Spaltenliste sogar
d_contact.

Desweiteren wäre es besser, unter GROUP BY mit der ID zu arbeiten.


> FROM contact, email
> WHERE ad_email.person_id = ad_contact.id
> OR ad_email.person_id is NULL";
> GROUP BY name, first_name";

In diesem Fall ist die OR-Bedingung absolut wirkungslos, der Unterschied
besteht m.E. hier darin, daß Du Deinen String (vermutlich im
Anwendungsprogramm?) bereits nach NULL mit "; abschließt.


> dann bekomme ich alle Name und eMail Adressen ausgegeben, auch die
> Namen ohne eMail, aber es werden alle Eintraege ausgegeben
> (Doppeltnennungen).

Weil das GROUP BY eben deshalb nicht greift.

Was mich wundert, ist, daß für das alleinstehende

| GROUP BY name, first_name";

keine Syntaxfehler im Programm auftaucht.


Thomas
--
Das ist keine Signatur, es handelt sich nur um eine Signatur-Attrappe.

Re: Datenbankabfrage dieser Art moeglich?

am 15.08.2006 22:26:37 von Hannes

Hallo Thomas,

verstehe ich Dich richtig, dass ein LEFT JOIN mir vlt. weiter helfen
kann?
Vielen Dank fuer den Tipp.

> Das ist eher ungünstig; für diesen Zweck gibt es extra die Konstrukte=
USING
> und ON. Lies Dir am besten nochmal den entsprechenden Abschnitt im Handbu=
ch
> durch (Stichwort JOIN).
Ok, werde ich beachten. Danke, fuer den Hinweis.

> Außerdem paßt Dein Query oben nicht - eigentlich sollte hier ein Fehl=
er
> auftreten, weil Du unter FROM die Tabellen contact und email stehen hast,
> unter WHERE aber ad_email und ad_contact, in der Spaltenliste sogar
> d_contact.
Fehler tritt nicht auf, dann die eigentlichen Bezeichnung der Tabellen
mit ad_* beginnen. Damit es nicht so verwirrend ist, wollte ich die
Tbl. fuer das posting umbenennen, vergass aber auch in den Bedingungen
die Namen zu aendern.

> Desweiteren wäre es besser, unter GROUP BY mit der ID zu arbeiten.
Klingt logisch.

Vielen Dank fuer die Hinweise.

Viele Gruesse,
Hannes Hapke

PS.: Nachname sollte jetzt auch als Benutzer erscheinen. Sorry, ist
mir nicht aufgefallen, dass ich diesen Eintrag vergessen hatte.

Re: Datenbankabfrage dieser Art moeglich?

am 16.08.2006 11:25:32 von Thomas Rachel

Hannes wrote:

> Hallo Thomas,
>
> verstehe ich Dich richtig, dass ein LEFT JOIN mir vlt. weiter helfen
> kann?

Ganz genau. Bei einem normalen Join wird ein Datensatz, der nur in einer
Tabelle vorkommt, weggelassen, bei einem "richtungsgebundenen" (LEFT/RIGHT)
JOIN wird auf der "Gegenrichtung" zur angegebenen Richtung NULL eingefügt,
wenn es keinen gibt.

> Vielen Dank fuer die Hinweise.

Gern geschehn.

> P.S.: Nachname sollte jetzt auch als Benutzer erscheinen.

Nö, noch nicht...


Thomas
--
Blödsinnige Liedtexte, Teil 4:
"Nadeln und Geheimnummern"
"Arrqyrf Naq Cvaf"

Re: Datenbankabfrage dieser Art moeglich?

am 16.08.2006 20:41:08 von Joachim Zobel

On Tue, 15 Aug 2006 12:27:32 -0700, Hannes wrote:

> Es sollen alle Namen aus contact ausgegeben mit der moeglicherweise
> vorhanden eMail Adresse, aber jeder Name nur einmal (erste auftauchende
> eMail zu Name reicht).

MIN oder MAX hilft fuers "nur einmal", der Rest ist ja schon klar.

Gruß,
Joachim

--
Warnung: \" kann Augenkrebs verursachen.