SQL: Tabellen mit Joins vergleichen (left join)

Für ein Newsletter-Cleint musste ich Daten von einer Webseite in eine Adress-tabelle einlesen.
Die Eingelesenen Adressen sollten natürlich nicht doppelt vor kommen – und ich wollte möglcihst wenig aufwand damit haben.
Darum habe ich mich entschieden das Problem in SQl zu lösen.

Im Prinzip geht es hier Darum, dass die Daten in eine 2. Tabelle geschrieben werden und diese dann mit er eigentlichen Tabelle vergleichen werden.

Als erstes legen wir die Eigentliche Adress-tabelle an – und passend dazu ein paar Datensätze.

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE [Adressen] (
  [id] INTEGER NOT NULL PRIMARY KEY, 
  [vorname] VARCHAR(50), 
  [name] VARCHAR(50), 
  [email] VARCHAR(100)
  );
 
INSERT INTO Adressen (vorname,name,email) VALUES ('Karl','Einzer','karl@einzer.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Helmut','Zweier','helmut@zweier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Paul','Dreier','paul@dreier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Egon','Vierer','egon@vierer.de');

Danach sieht der Inhalt der Tabelle so aus:

RecNo id vorname name   email            
----- -- ------- ------ ---------------- 
    1  1 Karl    Einzer karl@einzer.de   
    2  2 Helmut  Zweier helmut@zweier.de 
    3  3 Paul    Dreier paul@dreier.de   
    4  4 Egon    Vierer egon@vierer.de  

Als nächstes legen wir die 2. tabelle an wo die Datensätze rein geschrieben werden, welche vom Web abgerufen werden.
Der Aufbau ist identisch zur eigentlichen Adress-Tabelle – es stehen nur andere Daten drin.
Darum schrieben wir auch gleich ein paar abweichende Daten in die Tabelle (passiert normalerweise durch die Web-Einlese-Schnittstelle).

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE [Adressen_tmp] (
  [id] INTEGER NOT NULL PRIMARY KEY, 
  [vorname] VARCHAR(50), 
  [name] VARCHAR(50), 
  [email] VARCHAR(100)
  );
 
INSERT INTO Adressen_tmp (vorname,name,email) VALUES ('Corinna','Fuenfer','corinna@fuenfer.de');
INSERT INTO Adressen_tmp (vorname,name,email) VALUES ('Marion','Sechser','marion@sechser.de');
INSERT INTO Adressen_tmp (vorname,name,email) VALUES ('Johanna','Siebener','johanna@siebener.de');
INSERT INTO Adressen_tmp (vorname,name,email) VALUES ('Jennifer','Achter','jennifer@achter.de');

Diese Tabelle sieht danach so aus:

RecNo id vorname  name     email               
----- -- -------- -------- ------------------- 
    1  1 Corinna  Fuenfer  corinna@fuenfer.de  
    2  2 Marion   Sechser  marion@sechser.de   
    3  3 Johanna  Siebener johanna@siebener.de 
    4  4 Jennifer Achter   jennifer@achter.de  

Jetzt brauchen wir eine Abfrage welche die Datensätze zurück liefert zu denen es in Tabelle „Adressen“ keine passenden Datensätze ui denen in „Adressen_tmp“ gibt:

1
2
3
4
5
6
7
8
9
SELECT 
       Adressen.id,
       Adressen_tmp.vorname,
       Adressen_tmp.name,
       Adressen_tmp.email
FROM 
     Adressen_tmp
LEFT JOIN Adressen ON 
     Adressen.email = Adressen_tmp.email

Daraus resultiert das folgende Ergebnis:

   
    id vorname  name     email       
------ -------- -------- ------------------- 
(null) Corinna  Fuenfer  corinna@fuenfer.de  
(null) Marion   Sechser  marion@sechser.de   
(null) Johanna  Siebener johanna@siebener.de 
(null) Jennifer Achter   jennifer@achter.de  

Was ist jetzt aber wenn es in beiden Tabellen die selbe Email Adresse gibt?
Dafür nehmen wir uns erstmal einen Datensatz aus der Tabelle „Adressen“ und tragen ihn in die Tabelle „Adressen_tmp“ ein:

1
INSERT INTO Adressen_tmp (vorname,name,email) VALUES ('Egon','Vierer','egon@vierer.de');

Selbige JOIN Abfrage wie oben auf den neuen Inhalt der Tabelle sieht nun so aus:

    id vorname  name     email               
------ -------- -------- ------------------- 
(null) Corinna  Fuenfer  corinna@fuenfer.de  
(null) Marion   Sechser  marion@sechser.de   
(null) Johanna  Siebener johanna@siebener.de 
(null) Jennifer Achter   jennifer@achter.de  
     4 Egon     Vierer   egon@vierer.de     

Der Datensatz mit der ID 4 wird hier also mit angezegt.
Um das zu verhindern suchen wir nur nach Datensätzen die in der Spalte id der ersten Tabelle NULL sind.

1
2
3
4
5
6
7
8
9
10
SELECT 
       Adressen.id,
       Adressen_tmp.vorname,
       Adressen_tmp.name,
       Adressen_tmp.email
FROM 
     Adressen_tmp
LEFT JOIN Adressen ON Adressen.email = Adressen_tmp.email
WHERE 
      Adressen.email IS NULL;

…und schon wird der überflüssige Datensatz nicht mehr mit angezeigt.

    id vorname  name     email               
------ -------- -------- ------------------- 
(null) Corinna  Fuenfer  corinna@fuenfer.de  
(null) Marion   Sechser  marion@sechser.de   
(null) Johanna  Siebener johanna@siebener.de 
(null) Jennifer Achter   jennifer@achter.de  

Soooo…
Das sind jetzt die Datensätze, welche in der Tabelle „Adresse_tmp“ existieren, aber nicht in der Tabelle „Adressen“ sind.
Das sind also die Datensätze die wir aus der „Adressen_tmp“ in die „Adressen“ übernehmen wollen.
Um dies zu erreichen, stellen wir den obigen Query einfach nur ein „INSERT INTO Adressen“ vorweg:

1
2
3
4
5
6
7
8
9
10
11
INSERT INTO Adressen
SELECT 
       Adressen.id,
       Adressen_tmp.vorname,
       Adressen_tmp.name,
       Adressen_tmp.email     
FROM 
     Adressen_tmp
LEFT JOIN Adressen ON Adressen.email = Adressen_tmp.email
WHERE 
      Adressen.email IS NULL;

… und schon sieht unsere Tabelle „Adressen“ wie folgt aus:

RecNo id vorname  name     email               
----- -- -------- -------- ------------------- 
    1  1 Karl     Einzer   karl@einzer.de      
    2  2 Helmut   Zweier   helmut@zweier.de    
    3  3 Paul     Dreier   paul@dreier.de      
    4  4 Egon     Vierer   egon@vierer.de      
    5  5 Corinna  Fuenfer  corinna@fuenfer.de  
    6  6 Marion   Sechser  marion@sechser.de   
    7  7 Johanna  Siebener johanna@siebener.de 
    8  8 Jennifer Achter   jennifer@achter.de  

Damit hätten wir erfolgreich den Inhalt einer Tabelle in eine andere geschrieben 🙂
Ich hoffe das Hilft jetzt irgendwen außer mir.

leave your comment


*

Unterstütze den Frickelblog!