Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

Normalisierung / Datenimport aus Excel

Begonnen von Mr. Ahnungslos, März 27, 2014, 13:31:10

⏪ vorheriges - nächstes ⏩

Mr. Ahnungslos

Also mal ganz laienhaft macht dieser Passus

ZitatWHERE NOT EXISTS
(SELECT NULL FROM KBS
WHERE KBS.Berater = B.ID AND KBS.Filiale = F.ID)

Folgendes: "WHERE NOT EXISTS" ist dann quasi wie ein Schalter zu verstehen, der die ganze voranstellende Abfrage sozusagen ein- und ausschalten kann. Ob der Schalter jetzt eingeschaltet ist, und somit die Anfügeabfrage ausgeführt wird hängt nun vom "WHERE..." ab. In diesem Fall wird das Abfrageergebnis, also das Wertepaar B.ID/F.ID (verbunden durch AND) mit den Datensätzen aus der Tabelle KBS Berater/Filiale verglichen und bei Vorhandensein wird der "Schalter" für die Gesamtabfrage quasi ausgeschaltet. Richtig verstanden?

Was bedeutet aber das SELECT NULL?

Mr. Ahnungslos

Hallo Eberhardt,

dank Deiner Unterstützung habe ich nun fast den kompletten Import fertig. Ich habe auch noch weitere Tabellen eingerichtet und den Import aus Daten_ALT erweitert (in der hochgeladenen Version der Datenbank waren noch nicht alle Felder vorhanden). Nun sieht das Meisterwerk wie folgt aus:

  'Import der Funktionsbezeichnungen aus Daten_Alt nach Tabelle Funktionen
   sSQL = "INSERT INTO Funktionen (Funktionsbezeichnung)" & _
          " SELECT DISTINCT Funktion FROM Daten_ALT D WHERE NOT EXISTS" & _
          " (SELECT Null FROM Funktionen G WHERE G.Funktionsbezeichnung = D.Funktion)"
   db.Execute sSQL, dbFailOnError

   'Import der Marktgebietsbezeichnungen aus Daten_Alt nach Tabelle Marktgebiete
   sSQL = "INSERT INTO Marktgebiete (Marktgebietsbezeichnung)" & _
          " SELECT DISTINCT Marktgebiet FROM Daten_ALT D WHERE NOT EXISTS" & _
          " (SELECT Null FROM Marktgebiete M WHERE M.Marktgebietsbezeichnung = D.Marktgebiet)"
   db.Execute sSQL, dbFailOnError

   'Import der Filialbezeichnungen aus Daten_Alt nach Tabelle Filialen (und Zuordnung des Fremdschlüssels für Marktgebiet)
   sSQL = "INSERT INTO Filialen ( Marktgebiet, Filialbezeichnung )" & _
          " SELECT DISTINCT M.ID, DA.Filialbezeichnung FROM Daten_ALT AS DA" & _
          " INNER JOIN Marktgebiete AS M ON DA.Marktgebiet = M.Marktgebietsbezeichnung" & _
          " WHERE Not EXISTS (SELECT NULL FROM Filialen AS F WHERE F.Filialbezeichnung = DA.Filialbezeichnung)"
   db.Execute sSQL, dbFailOnError
   
    'Import der Partnerklassen aus Daten_Alt nach Tabelle Partnerklassen
   sSQL = "INSERT INTO Partnerklassen (Partnerklasse)" & _
          " SELECT DISTINCT Partnerklasse FROM Daten_ALT D WHERE NOT EXISTS" & _
          " (SELECT Null FROM Partnerklassen M WHERE M.Partnerklasse = D.Partnerklasse)"
   db.Execute sSQL, dbFailOnError
   
       'Import der Branchen aus Daten_Alt nach Tabelle Branchen
   sSQL = "INSERT INTO Branchen (Branchenbezeichnung)" & _
          " SELECT DISTINCT Branche FROM Daten_ALT D WHERE NOT EXISTS" & _
          " (SELECT Null FROM Branchen M WHERE M.Branchenbezeichnung = D.Branche)"
   db.Execute sSQL, dbFailOnError
   
       'Import der Berufsgruppen aus Daten_Alt nach Tabelle Berufsgruppen
   sSQL = "INSERT INTO Berufsgruppen (Berufsgruppenbezeichnung)" & _
          " SELECT DISTINCT Berufsgruppe FROM Daten_ALT D WHERE NOT EXISTS" & _
          " (SELECT Null FROM Berufsgruppen M WHERE M.Berufsgruppenbezeichnung = D.Berufsgruppe)"
   db.Execute sSQL, dbFailOnError

   'Import der Beraternamen aus Daten_Alt nach Tabelle Berater (und Zuordnung des Fremdschlüssels für Funktionsbezeichnung)
   sSQL = "INSERT INTO Berater ( Funktion, Beratername )" & _
          " SELECT DISTINCT F.ID, DA.Kundenbetreuer FROM Daten_ALT AS DA" & _
          " INNER JOIN Funktionen AS F ON DA.Funktion = F.Funktionsbezeichnung" & _
          " WHERE Not EXISTS (SELECT NULL FROM Berater AS B WHERE B.Beratername = DA.Kundenbetreuer)"
   db.Execute sSQL, dbFailOnError

   'Befüllen der Tabelle KBS mit den Fremdschlüsseln zu Berater und Filiale
   sSQL = "INSERT INTO KBS ( Berater, Filiale )" & _
        " SELECT DISTINCT B.ID, F.ID FROM Filialen AS F INNER JOIN" & _
        " (Berater AS B INNER JOIN Daten_ALT AS DA ON B.Beratername = DA.Kundenbetreuer)" & _
        " ON F.Filialbezeichnung = DA.Filialbezeichnung" & _
        " WHERE Not EXISTS (SELECT NULL FROM KBS WHERE KBS.Berater = B.ID AND KBS.Filiale = F.ID)"
   db.Execute sSQL, dbFailOnError


Funktioniert Super, jedoch werden leere Feldinhalte aus Daten_ALT in den einzelnen Tabellen doch immer wieder als neuer Datensatz angeführt. Fehlt zum Beispiel bei einem Kunden die Branche oder die Berufsgruppe, so wird in der Tabelle "Branchen" immer wieder ein Datenstz angefügt, der jedoch keinen Inhalt aufweist. Hier scheint die Bedingung "WHERE NOT EXISTS" nicht zu greifen. Ist das begehbar?

Beste Grüße

Michael

ebs17

#17
Zitat"WHERE NOT EXISTS" ist dann quasi wie ein Schalter zu verstehen ...
Nein. Eine WHERE-Bedingung ist ein Filter. Wenn man per Datenlage und Filter ein leeres Recordset erzeugt, kann natürlich nichts angefügt werden.

EXISTS erzeugt True oder FALSE, je nach dem, ob es in der Unterabfrage korrespondierende Datensätze zur Hauptabfrage gibt. Dabei ist es in dieser Gestaltung egal, ob oder welche Felder im SELECT-Teil der Unterabfrage aufgeführt sind (da es um Datensätze mit Kriterien geht). So kann man, statt irgendwelche Felder aufzuführen und dabei vielleicht den Eindruck zu erwecken, diese Felder hätten eine Bedeutung, auch eine Konstante zum "Füllen" des SELECT-Teils verwenden. In Anregung von Nouba verwende ich da NULL.
Einerseits "dokumentiert" NULL besonders schön die Bedeutungslosigkeit von Werten an dieser Stelle, andererseits müssen keine Werte in das Abfragerecordset geladen werden: Schlanke Recordsets sind performanter zu verarbeiten.

Eine andere Variante der Inkonsistenzprüfung wäre diese: Datensätze aus A, die nicht in B sind
Hier, wo sehr viele Tabellen zu verknüpfen wären, würde es aber ziemlich unübersichtlich bei dann vielen JOIN's bis vermutlich sogar problematisch.

Die Frage "leere Feldinhalte" musst Du selber zusätzlich lösen.
Denkbare Maßnahmen (auch im Kombination):
- Quelltabelle vor Import vervollständigen (oder insgesamt abweisen)
- In der Zieltabelle "Eingabe erforderlich" für das betrachtete Feld einstellen. Damit erzeugt ein leerer Inhalt einen Fehler.
- In der Abfrage für Ersatzeinträge sorgen.
- In der Abfrage Datensätze mit leeren Feldern ausfiltern. Diese Datensätze dann für den Import ignorieren oder aber mit Einzeleingaben und -anfügen nachtragen.

Und natürlich:
   sSQL = "INSERT INTO KBS ( Berater, Filiale, ... )" & _
        " SELECT DISTINCT B.ID, F.ID, ... FROM ..."

Wenn man Felder nicht in die Abfrage aufnimmt, können in der Zieltabelle keine Werte ankommen.
Mit freundlichem Glück Auf!

Eberhard