![]() |
Datenbank: Firebird • Version: 2.0 • Zugriff über: ADO.NET bzw. IBExpert Personal
[Erledigt] SELECT DISTINCT und JOIN - Redundanzen verringern
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):
Der folgende Versuch klappt nicht, weil Name2 und Name3 in mehreren Fassungen auftreten können.
SQL-Code:
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:
INSERT INTO Ziel (ID, Name1, Name2, Name3)
SELECT DISTINCT ID, Name1, Name2, Name3 FROM Quelle
SQL-Code:
Das sollte klappen; aber es dauert ewig, sodass IBExpert sich offensichtlich aufhängt.
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 Auch verschiedene Wege mit SELF-JOIN haben nur zum "Aufhängen" geführt, beispielsweise:
SQL-Code:
Natürlich sind zwei Sub-Selects hinderlich, aber die folgende Verkürzung ist syntaktisch nicht korrekt:
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
SQL-Code:
In der DP-Suche bin ich auf
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 ![]() Hat einer von Euch eine schöne Idee für mich? Recht herzlichen Dank! Jürgen |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Distinct zieht alle Felder der Abfrage mit ein, lass also ID mal weg.
|
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Aber den Vorschlag verstehe ich nicht: die ID ist ja eindeutig, und die will ich behalten. Von den unterschiedlichen Werten bei Name2 und Name3 will ich genau einen übernehmen (vorzugsweise einen mit Status = 'G'). Jürgen |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Ja, aber da ID eindeutig ist vewirkt das DISTINCT ja nichts.
|
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Außerdem: beziehst Du Dich auf einen speziellen meiner Versuche? Die verschiedenen Werte von Name2 und Name3, über die ich im Ergebnis hinwegsehen will, bringen FB beim DISTINCT wegen des PrimaryKey durcheinander. Jürgen |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Du musst erst mal definieren, was für dich ein identischer Datensatz ist. Und über diese Spalten musst du ein "select distinct" ausführen.
Willst du für diese Datensätze dann noch eine von eventuell mehreren IDs übernehmen, musst du ein Kriterium finden, welche ID genommen werden soll (z.B. jeweils die Kleinste). Das Kriterium muss über eine Agregatfunktion definierbar sein, wie z.B. Min Also könnte deine Abfrage in etwa so lauten:
SQL-Code:
select min(ID), Name2, Name3
from Tabelle group by Name2, Name3 |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Zitat:
Jürgen |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Beim DISTINCT wird überprüft ob alle Felder pübereinstimmen.
1, Peter, Achim, Tina 2, Peter, Achim, Tina sind dann verschieden! Wie sieht dein Schema aus? |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Bitte sehr:
Code:
Zieltabelle soll enthalten:
STR_ID STR_NR STATUS NAME_SORT NAME46 NAME22
--------------------------------------------------------------------- 837 1 S AGASTR Agastr. Agastr. 838 1 G AGATHAGASSE Agathagasse Agathagasse 839 1 G AGATHAPLATZ Agathaplatz Agathaplatz 840 1 S AGATHARIEDERSTR Agatharider Str. Agatharider Str. 840 1 G AGATHARIEDERSTR Agatharieder Str. Agatharieder Str. 841 1 G AGATHASTR Agathastr. Agathastr. 841 2 G AGATHASTR Agathastr. Agathastr. 841 3 G AGATHASTR Agathastr. Agathastr. 841 4 G AGATHASTR Agathastr. Agathastr. 841 5 G AGATHASTR Agathastr. Agathastr. 841 6 G AGATHASTR Agathastr. Agathastr. 842 1 G AGATHAWEG Agathaweg Agathaweg 843 1 G AGATHELASCHWEG Agathe-Lasch-Weg Agathe-Lasch-Weg
Code:
Jürgen
STR_ID NAME_SORT NAME46 NAME22
--------------------------------------------------------------------- 837 AGASTR Agastr. Agastr. // Status 'G' fehlt 838 AGATHAGASSE Agathagasse Agathagasse 839 AGATHAPLATZ Agathaplatz Agathaplatz 840 AGATHARIEDERSTR Agatharieder Str. Agatharieder Str. // Status 'G' vorziehen 841 AGATHASTR Agathastr. Agathastr. // Str_Nr 1 übernehmen 842 AGATHAWEG Agathaweg Agathaweg 843 AGATHELASCHWEG Agathe-Lasch-Weg Agathe-Lasch-Weg Nachtrag: Order by Status hilft mir nicht, weil es auch '1', '2' usw. als Status geben kann. |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Vielleicht sollte man auch mal das Schema richtigstellen. Welche Bedeutung ahben die verchiedenen Namen? Was bezweckst du mit der Abfrage (zu was die 2. Tabelle)?
|
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Zitat:
Und wenn ich dein nun endlich richtig verstanden hab, willst du für jede ID (837-843) jeweils einen einzigen Datensatz in deine Zieltabelle schreiben. Welcher, scheint dir egal zu sein... Da wird dir also nix anderes übrig bleiben, als DS für DS zu durchlaufen, sortiert nach ID, und sobald du eine neue ID erhälst, schreibst du den DS in deine Zieltabelle. Anders wird das wohl nicht klappen. |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Zitat:
Da ich (anders als die Post-Textdatei) mit einer relationalen DB arbeite, brauche ich sowieso getrennte Nachschlagetabellen mit einem PrimaryKey. Da bietet sich eine Tabelle "Straßennamen" an. Jürgen @Jelly Das, was Du zitiert hast, ist die Quelltabelle. "... jeweils einen einzigen Datensatz in deine Zieltabelle schreiben. Welcher, scheint dir egal zu sein..." Nicht ganz egal (ich bevorzuge Status 'G'), aber fast. |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Dann hol dir jeweils den 1. Datensatz mit der selben ID.
SQL-Code:
select STR_ID, MIN( name1), MIN(Name2), MIN(Name3) from Tabelle ORDER BY STR_ID;
|
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
Kann ich da noch den Status einbauen? Mir ist gerade die Idee gekommen, dass ich den Status 'G' durch '0' ersetzen könnte; dann wäre bei "Order By Str_ID, Status" der jeweils erste Treffer derjenige, den ich in die Zieltabelle nehmen möchte. Aber mir fehlt noch eine Idee, wie ich das mit "FIRST 1" kombinieren könnte. (Ich vermute, dass ein doppeltes SELECT mit SELF-JOIN zu meinen Problemen geführt hat.) Jürgen |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Oder eventuell so:
SQL-Code:
select StrId, Status, Name_Sort, Name46, Name22
from Tabelle where StrNr = 1 |
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Welchen Status willst du?
|
Re: SELECT DISTINCT und JOIN - Redundanzen verringern
Zitat:
|
Re: [Erledigt] SELECT DISTINCT und JOIN - Redundanzen verrin
Danke an Jelly und mkinzler,
aufbauend auf Euren Hinweisen habe ich es geschafft und dabei sogar den Status eingebaut. Die entscheidenden Ideen waren, MIN() zu verwenden mit passender Sortierung. Zusätzlich werden GROUP BY und ORDER BY sowie weiterhin DISTINCT benötigt. So sieht jetzt mein Code aus:
SQL-Code:
Alle Informationen werden so übernommen wie gewünscht; der bevorzugte Status 'G' musste vorher durch '0' (Null) ersetzt werden. Meine Idee dabei ist, dass der Status vor die (variablen) Namen gesetzt wird, dann der Minimalwert übernommen und vor dem Speichern wieder entfernt wird.
INSERT INTO STR_Namen
( ID, Aendg_per, Name_Sort, Name_lang, Name_kurz ) SELECT DISTINCT str_id, max(Geltung), min(Name_sort), SUBSTR(min(Status || Name46), 2,50), SUBSTR(min(Status || Name22), 2,50) FROM Quelle_Post_St GROUP BY Str_id, Name_sort ORDER BY Str_id, Name_sort Das Ganze läuft auch in akzeptabler Geschwindigkeit von weniger als zwei Minuten (nicht gemessen, nur gefühlt - bei 512 MB RAM). Danke für Eure Hilfe! Jürgen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:39 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz