Das Frettchen: Doppelte löschen als SQL-Statement

Mal ne Banane-Frage
Wie kann ich unter Access mit einer SQL-Abfrage doppelte Tupel löschen also Mehrfacheintragungen.
Wenn Email doppelt ist, dann bitte komplett die Zeile löschen.

Das Frettchen sagt danke!

  1. Hi,

    Wie kann ich unter Access mit einer SQL-Abfrage doppelte Tupel löschen also Mehrfacheintragungen.
    Wenn Email doppelt ist, dann bitte komplett die Zeile löschen.

    Welche Zeile löschen? (Das ist das Problem bei der Sache.)
    Nehmen wir an, Du hast zwei Zeilen mit Name1 und Name2, aber identischer Mail-Adresse. Möchtest Du jetzt Name1, Name2 oder beide löschen?

    SQL "denkt" mengenwertig, nicht sequentiell - das alleine wird Dein Vorgehen schon nicht ganz trivial werden lassen.
    Ginge es um identische Duplikate, also Zeilen, die in allen Spalten übereinstimmen, dann würde ich folgendes Vorgehensweise verwenden:

    1. Mehrdeutigkeit aller Adressen berechnen:
    CREATE TABLE tmp1 AS SELECT mailadr, COUNT (*) anzahl FROM tablename GROUP BY mailadr;

    2. Nun die eindeutigen wegwerfen (es geht auch anders, ist so aber verständlicher):
    DELETE FROM tmp1 WHERE anzahl = 1;

    3. Von den mehrdeutigen jeweils *genau ein* Exemplar sichern:
    CREATE TABLE tmp2 AS SELECT DISTINCT * from tablename WHERE mailadr IN (SELECT mailadr FROM tmp1);

    4. Jetzt alle mehrdeutigen Kandidaten löschen:
    DELETE FROM tablename WHERE mailadr in (SELECT mailadr FROM tmp1);

    5. Und nun die eindeutigen Adressen zurückkopieren:
    INSERT INTO tablename SELECT * FROM tmp2;

    Was für ein Aufwand!

    Deshalb ist die bessere Lösung diejenige, eine solche Situation gar nicht erst aufkommen zu lassen, indem Du für das Feld "mailadr" eine CONSTRAINT definierst, welche mehrdeutige Werte gar nicht erst erlaubt (dann wird bereits das INSERT einer solchen Zeile zurückgewiesen).
    Wie das genau in Access geht, weiß ich nicht - zur Not hilft es, einen UNIQUE INDEX über diese Spalte zu legen, was dieselbe Wirkung hat.

    mfG - Michael

  2. Moin Frettchen!

    IMHO Meine Access-Erfahrungen sind praktisch nicht vorhanden, aber Du kannst folgende (SQL92-Standard) SQL-Abfrage dafür nehmen:

    Angenommen
      1. Du willst aus "Tabelle" löschen
      2. Feld1, Feld2, ... Feldn sind Dein Vergleichskriterium, wenn die gleich sind, sollen die "alten" Datensätze gelöscht werden.
      3. Es gibt so etwas wie "rowindex" unter Access (müßte eine DataItem-Eigenschaft sein. Ein rowindex ist eine eindeutige pro Datensatz inkrementierte Zahl, die jedem Datensatz zur Verfügung steht.

    Dann müsste folgendes SQL-Statement:

    .delete from tabelle where rowindex in
    .  (select tab1.rowindex
    .   from tabelle tab1,
    .        tabelle tab2
    .   where tab1.feld1 = tab2.feld1 and
    .         tab1.feld2 = tab2.feld2 and
    .         ...
    .         tab1.feldn = tab2.feldn and
    .         tab1.rowindex != tab2.rowindex and
    .         tab1.rowindex != (select max(tab3.rowindex)
    .                           from tabelle tab3.rowindex
    .                           where tab1.feld1 = tab3.feld1 and
    .                                 tab1.feld2 = tab3.feld2 and
    .                                 ...
    .                                 tab1.feldn = tab2.feldn))

    eigentlich zum Ziel führen.
    Erklärung: Im ersten where werden alle Rowindexe von gleichen Spalten geholt, mit Ausnahme der höchsten (zuletzt eingefügten) Spalte (=Select 2)

    Achtung! Das Statement macht "full-table-scans", d.h. es geht die Tabelle komplett durch (mindestens 1x, eher, da kenne ich Access nicht, 3x), ist also laaaangsam.

    Hoffe es hilft Dir

    Gruß Jürgen

    1. Moins.

      Ja ne SQL Abfrage zum Löschen von mehrfach vorkommenden Einträgen?

      Hmm, Dupel und Trupel lassen sich schon mal feststellen durch:

      SELECT mailaddy FROM dbo.tbl WHERE Count(mailaddy) > 1

      dann speicherst du dir die Daten aus dem Recordset in  Variablen, führst eine Löschabfrage für alle mehrfach vorkommenden aus fügst dann wieder einen neuen Datensatz mit dem Inhalt der Variablen = Mailaddy und andere hinzu.

      <quelltext in etwa>

      set mymulti = db.execute(sql...)
      if mymulti.EOF or mymulti.BOF then Response.Write "No Duplicates"

      ELSE
      Do until mymulti.EOF

      tempvar = mymulti("mailaddy")
      sql2 = "DELETE FROM dbo.tbl WHERE mailaddy = '" & tempvar &"'"
      db.execute(sql2)

      sqlneu = "INSERT INTO dbo.tbl (mailaddy) Values ('"& tempvar &"')"
      db.execute(sql3)

      mymulti.Movenext
      Loop

      So viel Spaß beim Ausprobieren..

      Frank (.. der langsam ASP/SQL verrückt wird)

      Ciao