Hallo,
mit folgendem SQL-String komme ich an die Grenzen:
DELETE FROM [CC-firmen]
WHERE NOT EXISTS (
SELECT [CC-firmen].ID FROM (
SELECT [CC-firmen].ID AS FilterID FORM [CC-firmen]
LEFT JOIN Ansprechpartner ON [CC-firmen].ID=Ansprechpartner.ID_CC
LEFT JOIN Kategorie ON [CC-firmen].ID=Kategorie.ID_CC
LEFT JOIN Kontakte ON Ansprechpartner.ID=Kontakte.ID_AP
WHERE ([CC-firmen].Stadt) Like 'Frankfurt')
WHERE [CC-firmen].ID = FilterID)
Hintergrund ist der:
In einem Suchformular erstelle ich eine SQL-Abfrage, um Datensätze zu selektieren. Das ist der "innere" Select mit den vielen Joins. Für das Beispiel "Frankfurt" bräuchte es die zwar nicht, aber es ist ja nur ein Beispiel.
Nun soll das Statement hier alle Datensätze AUSSER den selektierten löschen. (So dass in der Tabelle nur Datensätze aus Frankfurt übrig bleiben). Keine Ahnung, ob das mit dem Konstrukt überhaupt klappt, aber zum Ausprobieren komme ich ja gar nicht, denn:
Access meldet den Fehler, dass ein reserviertes Wort oder ein Argumentname falsch oder fehlend wäre...
Hallo,
nur zur Syntax:
SELECT [CC-firmen].ID AS FilterID FORM From [CC-firmen]
Schon mal Danke!
Irgendwann wird man betriebsblind und sieht gar nix mehr...
Nun ist der Fehler "Fehlender Operator"...
Hallo,
schau mal, ob die Klammerung der Left Joins nötig/richtig ist, indem Du diese Unterabfrage erst mal im Abfrageentwurf generierst.
Ich würde einiges bemängeln:
1)
SELECT [CC-firmen].ID FROM (SELECT ...)
WHERE [CC-firmen].ID = FilterID)
Wenn die Datenherkunft eine Unterabfrage ist, kann man die Felder nicht auf irgendeine Tabelle qualifizieren.
2)
SELECT [CC-firmen].ID AS FilterID FORM [CC-firmen]
LEFT JOIN ...
WHERE ([CC-firmen].Stadt) Like 'Frankfurt'
LEFT JOIN heißt alle Datensätze aus der linken Tabelle, was dann bedeutet, dass man das restliche Zeugs auch weglassen kann. Eine Filterung ohne Filterung ist überflüssig.
3)
WHERE ([CC-firmen].Stadt) Like 'Frankfurt'
Das ist bezüglich Indexnutzung ein Sündenfall.
MfGA
ebs
Zitat von: ebs17 am August 06, 2011, 19:58:04
Ich würde einiges bemängeln:
1)
SELECT [CC-firmen].ID FROM (SELECT ...)
WHERE [CC-firmen].ID = FilterID)
Wenn die Datenherkunft eine Unterabfrage ist, kann man die Felder nicht auf irgendeine Tabelle qualifizieren.
2)
SELECT [CC-firmen].ID AS FilterID FORM [CC-firmen]
LEFT JOIN ...
WHERE ([CC-firmen].Stadt) Like 'Frankfurt'
LEFT JOIN heißt alle Datensätze aus der linken Tabelle, was dann bedeutet, dass man das restliche Zeugs auch weglassen kann. Eine Filterung ohne Filterung ist überflüssig.
3)
WHERE ([CC-firmen].Stadt) Like 'Frankfurt'
Das ist bezüglich Indexnutzung ein Sündenfall.
Danke für die Antwort!
zu 1.
Wenn Du FilterID meinst - das habe ich mit AS festgelegt, da ich sonst zwei gleich benamte Felder hätte.
Die Filterabfrage bezieht sich eben auf die selbe Tabelle wie die, aus der ich löschen will.
Falls Du was anderes meinst, müsstest Du mir das nochmal erklären.
zu 2.
Der Left join liefert mir Daten, die ich bei anderen Filterkriterien brauche - nur nicht hier in dem Beispiel. Diese Selektion läuft zur Filterung auch einwandfrei. Da allerdings noch als SELECT DISTINCT.
zu 3.
Ich weiß, ich lebe in Sünde... Allerdings gibt es neben dem Primärindex eh keine Indices, da es nur ein paar hundert Sätze sind. Und wenn ich Selektiere, will ich Frankfurt* nutzen können.
Hallo,
ZitatSo dass in der Tabelle nur Datensätze aus Frankfurt übrig bleiben
DELETE * FROM [CC-Firmen] WHERE [CC-Firmen].Stadt <> 'Frankfurt'
EDIT:
...und warum nicht so?Sorry hab' daaaaas nicht beachtet...
ZitatDer Left join liefert mir Daten, die ich bei anderen Filterkriterien brauche ...
Daher versuche mal so ...:
DELETE FROM [CC-firmen]
WHERE NOT EXISTS (
SELECT FilterID FROM (
SELECT [CC-firmen].ID AS FilterID FORM [CC-firmen]
LEFT JOIN Ansprechpartner ON [CC-firmen].ID=Ansprechpartner.ID_CC
LEFT JOIN Kategorie ON [CC-firmen].ID=Kategorie.ID_CC
LEFT JOIN Kontakte ON Ansprechpartner.ID=Kontakte.ID_AP
WHERE ([CC-firmen].Stadt) = 'Frankfurt')
WHERE [CC-firmen].ID = FilterID)
... auch wenn' sündig ist - dadurch wird's ja erst richtig interessant ;) ;D
Qualifizierung von Feldbezeichnungen heißt, dass zusätzlich zum Feldnamen die Herkunftstabelle des Feldes angegeben ist. Dabei sollten sich die im SELECT-Teil verwendeten Tabellen im FROM-Teil wiederfinden können. Das ist bei Dir nicht der Fall:
[CC-firmen] <> (SELECT ...)
Tabellenalias wäre ein Stichwort, das einen bei geschachtelten Abfragen wie auch bei Mehrfachverwendung der gleichen Tabelle weiter bringen kann.
Zu 2) In Abfragen unnützes Zeug mitzuführen ist fehleranfällig (wie sichtbar) und macht unnötigen Aufwand bei der Abfrageausführung. In diesem Sinne würde mein Vorschlag zu dieser Abfrage sehr ähnlich zu dem von database aussehen. (Schon zur Gewohnheitsbeibehaltung würde ich eine Indexnutzung ermöglichen.)
Wenn man Abfragen schreiben kann, hält sich der Stolz auf eine in einer bestimmten Situation funktionierende Abfrage derart in Grenzen, dass man sie nicht laufend wiederverwenden muss, sondern man schreibt einfach eine passende schlanke Abfrage.
MfGA
ebs
Ahhhh!
FilterID nach vorne - genial!
Allerdings fragt er nach dem Parameterwert für CC-firmen.ID
Nur wo?
EDIT:
Müsste doch hier sein WHERE [CC-firmen].ID = FilterID
Nur wieso?
Ich habe, da ich mit EXISTS nicht auskenne, folgendes Beispiel im Web gefunden
SELECT *
FROM suppliers
WHERE not exists (select * from orders Where suppliers.supplier_id = orders.supplier_id);
Da liegen wir doch nun genau drauf, oder?
Hallo,
überprüfe mal bitte die Schreibweise ALLER gleichlautenden Feldbezeichungen in deinem Statement!
Ich habe deine Abfrage nachgestellt ... hier mein Statement, das fehlerlos abläuft:
SELECT SP_ID
FROM Sonderpruefungen
WHERE NOT EXISTS
(SELECT FilterID FROM
(SELECT SP_ID as FilterID FROM Sonderpruefungen
WHERE SPruefung = 'Bierkiste')
WHERE SP_ID = FilterID);
... und auch die Feldbezeichnungen in den beteiligten Tabellen!
EDIT:
Du kannst aber auch versuchen analog des Vorschlags von ebs17 Aliasnamen zu verwenden, dann wirds vielleicht einfacher zu finden sein:
DELETE FROM [CC-firmen] AS Erste
WHERE NOT EXISTS (
SELECT FilterID FROM (
SELECT Zweite.ID AS FilterID FORM [CC-firmen] as Zweite
LEFT JOIN Ansprechpartner ON Zweite.ID=Ansprechpartner.ID_CC
LEFT JOIN Kategorie ON Zweite.ID=Kategorie.ID_CC
LEFT JOIN Kontakte ON Ansprechpartner.ID=Kontakte.ID_AP
WHERE Zweite.Stadt = 'Frankfurt')
WHERE Erste.ID = FilterID)
... und auch dazu mein funktionierendes Teststatement:
SELECT Erste.SP_ID
FROM Sonderpruefungen AS Erste
WHERE NOT EXISTS
(SELECT FilterID FROM
(SELECT Zweite.SP_ID as FilterID FROM Sonderpruefungen AS Zweite
WHERE Zweite.SPruefung = 'Bierkiste')
WHERE Erste.SP_ID = FilterID);
HTH
Ui!
So SELECT * FROM [CC-firmen] AS erste
WHERE NOT EXISTS (
SELECT FilterID FROM
( SELECT DISTINCT [CC-firmen].ID AS FilterID FROM (([CC-firmen]
LEFT JOIN Ansprechpartner ON [CC-firmen].ID=Ansprechpartner.ID_CC)
LEFT JOIN Kategorie ON [CC-firmen].ID=Kategorie.ID_CC)
LEFT JOIN Kontakte ON Ansprechpartner.ID=Kontakte.ID_AP
WHERE [CC-firmen].Stadt Like 'Frankfurt'
)
WHERE erste.ID = FilterID )
Funktioniert es ohne Nachfrage.
Nur kann ich so meinen SQL- String aus dem Selektionsformular nicht mehr verwenden. >:(
EDIT:
Uff - es klappt auch mit "erste" als einzigem Alias! - gerettet!
... hast du meinen Vorschlag mit den Aliasen für die Tabellennamen versucht?
EDIT
Eben gesehen ...
ja klar funktioniert es in deinem Fall mit nur einem Alias, dieses unterscheidet ja bereits die Tabellennamen ... ! ;D ;)
... und nach Adam Riese kann ich mir dann auch den Feldalias sparen.
Klappt bestens!
Danke nochmal an alle!
... und verpassen Sie nicht die nächste spannende Folge von "Elwood blickt's nicht!"...
... setze aber VOR der Fortsetzung diesen Thread in DEINEM ersten Beitrag bitte auf 'gelöst'
DANKE!
;D ;)