Hallo Rolf,
Und damit wäre mein Ansatz dieser: eine Work-Table mit einen NON-UNIQUE Index, so dass Duplicates erstmal kein Problem sind, aber ein GROUP BY effizient via Index möglich ist. Und dann die Duplikate ausblenden. Das geht mit row-value-expressions und NOT IN.
Haha...diese Tabelle existiert bereits 😉 Es ist tatsächlich so, dass ich eine temp_table habe, die ohne Unique-Index (mal vom Primary-Key abgesehen) läuft und aus der ohnehin die Daten 1:1 in die real_table-Tabelle kopiert werden sollen. Und genau das scheitert, wenn Feld2+Feld3 zweier Datensätze identisch sind, weil ich einen kombinierten Unique-Index auf Feld2+Feld3 liegen habe.
Angenommen, die Tabelle, in die der wirkliche Import stattfinden soll, hieße
real_table
. Dann gelingt es mit folgender Magie:INSERT INTO real_table (feld1, feld2, feld3, feld4, feld5, feld6) SELECT feld1, feld2, feld3, feld4, feld5, feld6 FROM temp_table WHERE (feld2, feld3) NOT IN (SELECT feld2, feld3 FROM temp_table GROUP BY feld2, feld3 HAVING COUNT(*) > 1)
(feld2, feld3) ist eine row-value-expression. Sowas kannte ich bisher nur vom DB2 unseres Großrechners, und hielt es für eine nützliche, aber ansonsten unbekannte IBM Erweiterung. Weit gefehlt, das ist SQL-92 und es funktioniert z.B. auch in MYSQL 5.6.
Das muß ich unbedingt ausprobieren... hört sich zu schön an, um wahr zu sein 😀
Soviel zu meiner Hypothese, dass man den IN Operator nur für Skalare einsetzen könnte.
Ich dachte kurz, man könnte das auch mit einem JOIN nachbilden, aber das führt (logischerweise) bei N Duplicates zu einer Ver-N-fachung der eindeutigen Sätze. Man müsste also noch einen DISTINCT nachschalten. Ich glaube nicht, dass das effizient ist.
Was übrigens nicht geht, ist ein Vorfiltern der Duplikate auf diese Weise:
DELETE FROM temp_table WHERE (feld2, feld3) IN (SELECT feld2, feld3 FROM temp_table GROUP BY feld2, feld3 HAVING COUNT(*) > 1)
Grund: Ich darf in der WHERE Klausel eines DELETE nicht die Tabelle verwenden, aus der gelöscht wird. Wenn man die Duplikatsätze löschen will, müsste man eine Zwischentabelle haben, in der man die (feld2, feld3) Paare speichert, die zu löschen sind.
Schade, aber einleuchtend. Aber wenn obige Query läuft (ich kanns erst morgen früh probieren), wäre ich sehr zufrieden.
Auf jeden Fall Danke für den Tip!
...der war gut 😀
Pit