il-wega1
Goto Top

SQL NOT EXISTS

Hallo zusammen,

ich habe folgende Anforderung, die ich auch schon gelöst hab.
Leider jedoch mit sehr langer Zugriffszeit.
Eventuell kann mir einer einen Tip geben wie es performanter gelöst werden kann.

Ich muss Daten aus einer Tabelle anzeigen, die in zwei anderen Tabellen nicht enthalten sind.

wie ich es gelöst habe:

SELECT data
FROM t1
WHERE
(NOT EXISTS
(SELECT data
FROM t2
WHERE (data COLLATE SQL_Latin1_General_CP1_CI_AS = t1.data)))
AND (NOT EXISTS
(SELECT data
FROM t3
WHERE (data COLLATE SQL_Latin1_General_CP1_CI_AS = t1.data)))


Ergebnis ist dann alle Daten aus t1 die weder in t2 noch in t3 vorhanden sind.


Danke schon vorab für die Unterstützung

Content-Key: 526236

Url: https://administrator.de/contentid/526236

Printed on: April 19, 2024 at 14:04 o'clock

Member: SlainteMhath
SlainteMhath Dec 17, 2019 at 09:58:03 (UTC)
Goto Top
Moin,

sollte das nicht auch mit LEFT JOINS gehen?
Etwa so:
SELECT data
FROM t1
LEFT JOIN t2 ON t1.data = t2.data
LEFT JOIN t3 ON t1.data = t3.data
WHERE t2.data = NULL and t3.data = NULL

Bei deinem SELECT / NOT EXIST wälzt er für jede Zeile aus t1 t2 und t3 von neuem durch... das kann nicht schnell sein. Sind wenigstens entsprechende Indizis in den Tabellen gesetzt?

lg,
Slainte
Member: il-wega1
il-wega1 Dec 17, 2019 at 10:18:19 (UTC)
Goto Top
LEFT JOIN kommt leider zu keinem Ergebnis...

Ich benötige alle Daten aus t1 die weder in t2 noch in t3 vorhanden sind.
Wenn ein Datensatz in t2 oder t3 enthalten ist soll er nicht angezeigt werden.
Da es unterschiedliche Datenabnken sind muss ich COLLATE SQL_Latin1_General_CP1_CI_AS verwenden um keinen Fehler zu erzeugen.

t1	t2	t3	Ergebnis
1	5	1	4
2	6	2	8
3	7	3	9
4			
5			
6			
7			
8			
9			
Member: akretschmer
akretschmer Dec 17, 2019 at 13:39:20 (UTC)
Goto Top
test=# create table t1 as select * from generate_series(1,9) s;
SELECT 9
test=*# create table t2 as select * from generate_series(5,7) s;
SELECT 3
test=*# create table t3 as select * from generate_series(1,3) s;
SELECT 3
test=*# select * from t1 except (select * from t2 union all select * from t3);
 s 
---
 9
 4
 8
(3 rows)

test=*#
Member: il-wega1
il-wega1 Dec 17, 2019 at 14:11:15 (UTC)
Goto Top
Danke für die Antwort,
diese Variante hab ich auch erfolgreich getestet.
Hat aber in etwa dieselbe Performance wie die NOT EXISTS Strategie, mit dem Nachteil das keine zusätzlichen Daten mit abgefragt werden können.
Member: akretschmer
akretschmer Dec 17, 2019 at 14:53:42 (UTC)
Goto Top
was die Performance betrifft: muß man schauen, wie der Plan ist, wie die Tabellen wirklich aufgebaut sind, ob es einen PK gibt etc.. Zusätzliche Daten abfragen? Wo ist da das Problem?
Member: ukulele-7
ukulele-7 Dec 17, 2019 at 15:41:38 (UTC)
Goto Top
Der Spaltenname "data" hört sich auch fies an, du vergleichst also extrem große Datensätze. Gibt es einen eindeutigen Key der abgeglichen werden kann?

Eventuell hilft ein Index auf der data Spalte der jeweiligen Tabelle aber das kann natürlich Performance Probleme beim Schreiben geben.
Member: GrueneSosseMitSpeck
GrueneSosseMitSpeck Dec 19, 2019 updated at 09:02:14 (UTC)
Goto Top
Zitat von @il-wega1:

Danke für die Antwort,
diese Variante hab ich auch erfolgreich getestet.
Hat aber in etwa dieselbe Performance wie die NOT EXISTS Strategie, mit dem Nachteil das keine zusätzlichen Daten mit abgefragt werden können.

der MS SQL Server optimiert das in outer joins, ich meine ab Version SQL 2000 oder 2005. Braucht halt so oder so genug Arbeitsspeicher um den outer join im Arbeitsspeicher halten zu können.

Für andere Serverprodukte muß man das austesten, was der Server X oder Y am effektivsten abarbeitet.