Supportnet Computer
Planet of Tech

Supportnet / Forum / Datenbanken

Kleines Abfrage Problem





Frage

Ich habe in meiner Datenbank folgende Abfrage SELECT Adressen.Firma, Adressen.Abteilung, Adressen.Stadt, Adressen.Straße, Adressen.ID FROM Adressen, [Kopie von Adressensuchen], [Kopie von Name->FirmenID] WHERE (((Adressen.ID)=[Kopie von Name->FirmenID]![ID] Or (Adressen.ID)=[Adressensuchen]![ID])) GROUP BY Adressen.Firma, Adressen.Abteilung, Adressen.Stadt, Adressen.Straße, Adressen.ID; Das ganze ist teil einer Volltextsuche in einer Adresssammlung, die aus 2 Tabellen besteht, in der 1. stehen die Adressen und Firmennamen, in der 2. sind den Firmen verschiedene Ansprechpartner zugeordnet. Die beiden Abfragen Name->FirmenID und Adressensuchen liefern nun jeweils die ID´s aller Einträge zurück die den Suchkriterien entsprechen, diese Abfrage soll nun den ID´s zugeornete Firmen ausgeben, dies tut sie aber nur wenn beide Abfragen Ergebnisse liefern, wenn eine von beiden nichts findet bleibt auch das Gesamtergebnis leer. Warum ist das so?

Antwort 1 von Flooooo

Zitat:
dies tut sie aber nur wenn beide Abfragen Ergebnisse liefern


Das hat ein Join so an sich :-) - denn eine Bedingung ist ja, dass nur Tupel selektiert werden, die die "Gleichheitsbedingung" (id) erfüllen. Sprich: Wenn du einer Firma keinen Ansprechpartner zugeordnet hast, dann kommt dazu natürlich kein Datensatz raus, weil kein Tupel gefunden wird, bei denen die beiden Ansprechpartner-IDs gleich sind.

Antwort 2 von Woodman

Ja das ich keine Datensatz kriege wenn nicht gefunden wird is mir klar, aber wenn Name->FirmenID ein Ergebnis liefert, Adressensuchen aber nichts findet (seltener Name gesucht) bleibt das Ergebnis diese Abfrage leer, sobald beide Abfragen etwas finden werden alle Ergebnisse korrekt ausgegeben, was muss ich denn ändern damit ich die einzel Ergebnisse auch zu sehen bekomme? Für mich macht das irgendwie grad keinen Sinn, da steht doch ODER, also ist die Bedingung doch wahr wenn mindestens Eine ID passt oder nicht?

Antwort 3 von Flooooo

Kannst du vielleicht mal die Tabellenstrukturen posten, damit man sich nochmal ein genaues Bild machen kann, was in welcher Tabelle steht?

Antwort 4 von Woodman

Also

in Adressen
Firma, Abteilung, straße .... und ID als eindeutiger index

in Ansprechpartner
vorname, Nachname ... und die ID der zugehörigen Firma

Name->FirmenID durchsucht Ansprechpartner und gibt nur die ID´s zurück

Adressensuchen durchsucht Adressen und gibt auch die ID´s zurück

Die Abfrage soll jetz die ID´s der beiden Abfragen nehmen und Firmenname und so weiter ausgeben

Antwort 5 von Flooooo

Eben - was ist die Struktur von Adressensuchen?

Antwort 6 von Flooooo

So, ich hab glaub ich grob verstanden, was du willst. Punkt1: Das ist wieder so Access-Geschreddel, sorry, ich bin eher "SQL-Mensch" :-)

Prinzipiell würde die Abfrage in etwas so aussehen: (in etwa, weil ja adressensuchen und Name eigentlich SELECTS sind, die man in SQL auch hinschreiben wsürde; wie genau das in Access interpretiert werden kann - kA:


SELECT DISTINCT Adressen.Firma, Adressen.Abteilung, Adressen.Stadt, Adressen.Straße, Adressen.ID
FROM Adressen, Ansprechpartner, Adressensuchen, Name
WHERE 
	Adressen.FirmenID IN (Adressensuchen.FirmenID
				UNION
				Name.FirmenID)
	AND
	Adressen.FirmenID = Ansprechpartner.FirmenID;


Antwort 7 von Woodman

Ja Danke, für meinen Bedarf muss die AND Bedingung am Ende weg, aber Access mag den Ausdruck nich, habs jetz völlig unelgant gelöst indem ich die beiden Abfragen verschachtelt hab.

Antwort 8 von Flooooo

Wenn du aber die AND-Bed. weglässt, bekommst du ein Kreuprodukt! (Alle in der Suche enthaltenen FirmenIDs * Alle Ansprechpartner)

Antwort 9 von Woodman

Hab ich die UNION Anweisung ketz falsch verstanden? Ich dachte die würde aus den beiden Ergebnistabellen eine einzelne machen

Antwort 10 von Flooooo

@Woodman:

Ne, die Union hast du richtig verstanden, aber es passiert doch folgendes:

Schritt 0: Wir haben eine Tabelle "Adressen", die alle Adressen enthält, eine Tabelle "Ansprechpartner", die sämtliche bekannten Ansprechpartner (aller Firmen) enthält.
Dazu 2 Abfragen Adressensuchen und Name, die FirmenIDs enthalten, auf die die Suche zutraf. Ich gehe davon aus, dass "Adressensuchen" in den Adressen sucht und "Name" in der Ansprechpartner-Tabelle. (ist übrigens eigentlich ungeschickt, mehr dazu unten)

Schritt 1: (Adressensuchen.FirmenID UNION Name.FirmenID) fasst die beiden Suchergebnisse zusammen - d.h. hier entsteht eine Liste, die alle FirmenIDs enthält, auf die die Suche (gleich ob Name oder Adresse) zutrifft.

Schritt 2: Adressen.FirmenID IN Adressensuchen.FirmenID UNION Name.FirmenID) heißt nun in Prosa: Selektiere nur die Datensätze aus Adressen, die eine FirmenID besitzen, die in der Liste (Schritt 1) vorkommt.

Schritt 3: Würde man hier aufhören, so würde ja noch ein Kreuzprodukt auf Adressen & Ansprechpartner gebildet, d.h. jeder Firma aus der (eingeschränkten) Liste würde jeder Ansprechpartner zugeordnet, klar soweit? Deshalb noch die zweite Einschränkung AND Adressen.FirmenID = Ansprechpartner.FirmenID;


So, jetzt aber noch was anderes: Wieso teilst du dein Suchergebnis eigentlich vorher auf 2 Abfragen auf?

Besser wäre doch folgendes:

Eine Abfrage SELECT * FROM Adressen, Ansprechpartner WHERE Adressen.FirmenID = Ansprechpartner.FirmenID;

So, das liefert jetzt also eine Liste die jeweils Firma und Ansprechpartner als einen Datensatz enthält.

Und jetzt lass doch deine Suche am besten darauf los, und zwar auf "alle" Felder (z.B. Namen und Adressen) - die Einschränkung bekommst du dann ja direkt.



Antwort 11 von Woodman

Danke das klingt in der Tat einfacher als das logik chaos das ich grade benutze.
Aber wenn ich das richtig verstehe hab ich ein Problem, es kann in der Datenbank durchaus vorkommen das einer Firma kein Ansprechpartner zugeordnet ist, fallen diese Datensätze dann nicht raus?

Antwort 12 von Floooooo

Das stimmt, dann fallen sie raus.

Die schnellste Lösung wäre ein "Phantomansprechpartner", also z.B. der Partner mit der ID = 0 und dem Namen "Kein Ansprechpartner vorhanden" oder irgendsowas - die Beziehung zwischen den Tabellen muss dann referentielle Integrität besitzen, d.h. jeder Firma muss mind. 1 Anspreechpartner zugeordnet werden.

Antwort 13 von Floooooo

PS:

Ich persönlich finde die eben beschriebene Lösung (AW12) schöner, falls du das aber nicht so benuztzen möchtest, sondern wie bisher, wie wäre es dann einfach mit


SELECT * FROM Adressen, Ansprechpartner 
WHERE 
  Adressen.FirmenID = Ansprechpartner.FirmenID
OR
  Adressen.FirmenID NOT IN
      (SELECT FirmenID FROM Ansprechpartner);


Dann werden alle Firmen mit Ansprechpoartner selektiert und alle Firmen ohne Ansprechpartner.


Antwort 14 von Floooooo

Ups, Kommando zurück: Eigentlich darfv die eben genannte Abfrage nicht laufen, weil ja dann u.U. keine "Ansprchpartnerfelder" vorhanden sind...