November 24, 2020, 08:09:34

Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!


Kunden auslesen, welche nicht ware von einem Lieferanten bekommen haben.

Begonnen von Guido, Mai 06, 2010, 18:03:19

⏪ vorheriges - nächstes ⏩

Guido

Ich habe folgendes Problem.

Ich habe eine Datenbank mit mehreren tabellen unter anderem die Tabellen " Kundenadressen", "Auftrag" und "Auftragdetail"
diese sind mit einer Beziehung verknüpft.

Jetzt sollte ich für eine MArketing aktion alle Kunden haben, welche noch nicht von dem einen Hersteller waren bekommen haben.

Bis jetzt habe ich eine Abfrage erstellt. mit Feldern aus allen drei Tabellen. mit der Bedingung  [Auftragsdetail]![Lieferantennr]<> 4
jetzt zeigt es mir aber die Kunden mehrfach an, weil sie ja mehrere Artikeldetails auch von anderen Herstellern bekommen haben. und es zeigt  auch die an, welche bereits von diesem bekommen haben.
Wie kann ich die Kunden drausen halten, welche im gleichen oder auch in anderen Aufträgen von diesem Hersteller Ware bekommen haben.

database

Guten Morgen,

ich versuchs halt mal...

SELECT DISTINCT K.Feld1, K.Feld2, K.Feld3 FROM Kundenadressen K
      INNER JOIN Auftrag A ON A.KundenID = K.KundenID
      WHERE A.AuftragsID NOT IN(SELECT AuftragsID FROM Auftragdetail WHERE LieferantenNr =4)

Damit solltest du alle jene Kunden einfach angezeigt erhalten, bei deren Aufträgen der Lieferant 4 nicht vorkommt.

HTH
Peter

Guido

Danke für die schnelle antwort ich propiers mal heut abend.

LG Guido

Hondo

Hallo,
Not In ist bei vielen Datensätzen ein "Performancefresser".
Besser ist wie bei Donkarl beschrieben:
http://www.donkarl.com/?FAQ3.16

Andreas

database

Hallo,

Naja - also die Sache mit der Performance ist zweifelsfrei kritisch aber in Erwartung, dass die Abfrage nicht allzu oft ausgeführt werden wird (so schien es mir in der Frage) KANN man den Performance-Verlust verkraften - denke ich.
Zu Donkarls Tip - vielleicht habe ich jetzt nicht lange genug darüber gegrübelt aber ich sehe hier keinen direkten Tabellenvergleich und bis ein Konstrukt erzeugt ist, welches dann diese Vergleichsmöglichkeit bietet, ist die Abfrage auch schon durchgelaufen  :)
Aber technisch gesehen hast zweifelsohne recht Andreas!

Peter


Hondo

Also ich hatte in einem Projekt einen Datenimport der eine halbe Stunde lief, je nach importierten Datensätzen.
Nach Umstellen der Queries von not In nach Is Null dauerte dieser nur noch ca. 20 Sekunden.

Josef

Hallo!

Noch eine Anmerkung bezüglich Geschwindigkeit:
"Not in (..)" ist vor allem dann langsam, wenn der Select-Teil, der in IN(...) steht, viele DS zurück liefert. Solange nur wenige DS im In-Ergebnis vorkommen, ist das normalerweise relativ flott.
Ich vermute, dass dabei zuerst der IN-Teil ausgewertet wird und dann per cross join vergleichen wird. Leider lässt sich mit dem Jet-Showplan nicht herausfinden, was dabei genau passiert.

Manchmal hilft bereits die umgestrickte Variante auf "Not Exists".

z. B.:
.... WHERE NOT EXISTS (SELECT * FROM Auftragdetail X WHERE X.LieferantenNr = 4 AND X.AuftragsID = A.AuftragsID)


Am schnellsten ist bei Jet aber immer die Left-Join-Variante mit NULL-Prüfung, wie in FAQ 3.16 gezeigt. Bei dieser gelingt dem Jet-Abfrageoptimierer die Gestaltung eines besseren Ausführungsplans.

Für das obige Beispiel wäre das dann:
SELECT
  ....
FROM
    (Kundenadressen K
    INNER JOIN
    Auftrag A
    ON A.KundenID = K.KundenID)
    LEFT JOIN
    Auftragdetail AD
    ON (AD.AuftragsID  = A.AuftragsID  AND AD.LieferantenNr =4)


Diese SQL-Anweisung kann allerdings wegen dem Verknüpfungsausdruck nicht mehr in der Entwurfsansicht dargestellt werden.
Falls jemand lieber mit der Entwurfsansicht arbeitet, wäre folgendes gleichwertig:
SELECT
  ....
FROM
    (Kundenadressen K
    INNER JOIN
    Auftrag A
    ON A.KundenID = K.KundenID)
    LEFT JOIN
    (Select AuftragsID FROM Auftragdetail where LieferantenNr = 4) as AD
    ON AD.AuftragsID  = A.AuftragsID

Das sollte den gleichen Ausführungsplan erzeugen und lässt sich im Entwurfsmodus darstellen.


BTW: falls jemand auch mit dem MSSQL-Server arbeitet: dort ist der Abfrageoptimierer auch bei der IN-Anweisung so schlau, dass er sie nach Bedarf in eine Exists-Variante umformuliert. Dabei kann es dann je nach Datensituation dazu führen, dass alle 3 Varianten den gleichen Ablaufplan erhalten.


mfg
Josef


database

Morgääähn,

darf mich dem Dank von DF6GL anschließen...

LG

Peter

Guido

Super antworten danke. leder bin ich in SQL ein blutiger Anfänger und habe es nciht geschaft ohhne Fehlermeldungen

ich habe folgendes eingesetzt

SELECT Kundenadresse.Anrede, Kundenadresse.Vorname, Kundenadresse.Name, Kundenadresse.Strasse, Kundenadresse.Land, Kundenadresse.Postleitzahl, Kundenadresse.Ort, Auftrag.Kundenummer, Auftrag.Bestelldatum
FROM (Kundenadresse INNER JOIN Auftrag ON Kundenadresse.Kundennummer = Auftrag.Kundenummer)
LEFT JOIN     
(Select Auftrag.Auftragsnummer FROM Auftragsdetail where LieferantenNr = 2)
as Auftragsdetail  ON Auftragsdetail.Auftragsnummer  =  Auftrag.Auftragsnummer;

Bi Wechseln in die Ansicht fragt er mich nun nach den Parameterwerten von Auftrag.Auftragsnummer und LieferantenNr obwohl beide Felder vorhanden sind.
ich checks nicht
Lg Guido