Einzelnen Beitrag anzeigen

Jürgen Thomas

Registriert seit: 13. Jul 2006
Ort: Berlin
750 Beiträge
 
#1

[Erledigt] SELECT DISTINCT und JOIN - Redundanzen verringern

  Alt 21. Okt 2007, 13:27
Datenbank: Firebird • Version: 2.0 • Zugriff über: ADO.NET bzw. IBExpert Personal
Hallo,

ich bin dabei, eine nicht gut strukturierte Datendatei besser zu normalisieren, und habe Probleme, eine Liste eindeutiger Einträge zu erstellen. (Konkret: es handelt sich um die Straßendatei aus "Datafactory Postalcode" der Deutschen Post AG; ich möchte durch eine zusätzliche Tabelle mit eindeutigen Straßennamen die Wiederholungen reduzieren.)

Tabelle Quelle enthält etwa 260.000 Datensätze mit folgender Struktur (weitere vorhandene Felder können hier vernachlässigt werden):
  • ID, Nr, Status, Name1, Name2, Name3
Tabelle Ziel mit etwa 115.000 Datensätzen enthält nur noch diese Felder:
  • ID als PrimaryKey, Name1, Name2, Name3
ID und Name1 sind eindeutig. In der Tabelle Quelle stehen viele Datensätze mit diesen Werten, und auch die Kombination ID/Nr/Status ist nicht eindeutig. Ich möchte jeweils einen Eintrag aus "Quelle" nach "Ziel" übernehmen (vorzugsweise einen beliebigen mit Status='G') und finde keinen vernünftigen Weg.

Der folgende Versuch klappt nicht, weil Name2 und Name3 in mehreren Fassungen auftreten können.
SQL-Code:
INSERT INTO Ziel (ID, Name1, Name2, Name3)
SELECT DISTINCT ID, Name1, Name2, Name3 FROM Quelle
Mit dem folgenden Versuch erhalte ich zügig eine korrekte (und vollständige) Zieltabelle; aber ich finde keinen schnellen und einfachen Weg, die fehlenden Felder zu holen:
SQL-Code:
INSERT INTO Ziel (ID, Name1)
SELECT DISTINCT ID, Name1 FROM Quelle;

/* Teil einer StoredProcedure:
  danach zu jedem Eintrag die juengsten Angaben hinzufuegen  */

  FOR SELECT ID FROM Ziel INTO :current_id
  DO BEGIN
     FOR SELECT Name2, Name3
         FROM Quelle
        WHERE ID = :current_id
         INTO :current2, :current3
     DO BEGIN
        IF(passender Eintrag gemäß Status usw.)
        THEN BEGIN
          UPDATE STR_Namen
             SET Name2 = :current2,
                 Name3 = :current3
           WHERE ID = :current_id;
        END
     END
  END
Das sollte klappen; aber es dauert ewig, sodass IBExpert sich offensichtlich aufhängt.

Auch verschiedene Wege mit SELF-JOIN haben nur zum "Aufhängen" geführt, beispielsweise:
SQL-Code:
INSERT INTO Ziel
            ( ID, Name1, Name2, Name3 )
       SELECT DISTINCT st.ID, st.Name1,
              (SELECT FIRST 1 j.Name2
                                    FROM Quelle j
                                   WHERE st.ID = j.ID AND j.Status = 'G'),
              (SELECT FIRST 1 j.Name3
                                    FROM Quelle j
                                   WHERE st.ID = j.ID AND j.Status = 'G')
         FROM Quelle st
Natürlich sind zwei Sub-Selects hinderlich, aber die folgende Verkürzung ist syntaktisch nicht korrekt:
SQL-Code:
INSERT INTO Ziel
            ( ID, Name1, Name2, Name3 )
       SELECT DISTINCT st.ID, st.Name1,
              (SELECT FIRST 1 j.Name2, j.Name3
                                    FROM Quelle j
                                   WHERE st.ID = j.ID AND j.Status = 'G')
         FROM Quelle st
In der DP-Suche bin ich auf SQL-abfrage mit DISTINCT unterdruecken doppelter datensaetze gestoßen. Aber die dortigen Ideen konnte ich für ein SELF-JOIN nicht so umsetzen, dass genau ein zusätzlicher Datensatz geholt wird.

Hat einer von Euch eine schöne Idee für mich? Recht herzlichen Dank! Jürgen
#D mit C# für NET, dazu Firebird
früher: Delphi 5 Pro, Delphi 2005 Pro mit C# (also NET 1.1)
Bitte nicht sauer sein, wenn ich mich bei Delphi-Schreibweisen verhaue; ich bin inzwischen an C# gewöhnt.
  Mit Zitat antworten Zitat