Duplikate finden mit GROUP BY … HAVING
HAVING COUNT(*) > 1 nur Gruppen mit mehreren Zeilen behalten. MIN/MAX und eine Liste der IDs zeigen, welche Zeilen betroffen sind.🧪 Ausprobieren – Vorher / Nachher
SQL-Engine wird geladen …
🌍 Dialekte nebeneinander
Ausgeführt werden nur SQLite (sql.js) und – wo markiert – PostgreSQL (PGlite). MySQL/MariaDB, SQL Server und Oracle sind nach der offiziellen Dokumentation geschrieben, laufen hier aber nicht.
SELECT email, COUNT(*) AS anzahl, string_agg(kontakt_id::text, ',' ORDER BY kontakt_id) AS ids FROM kontakte GROUP BY email HAVING COUNT(*) > 1;
SELECT email, COUNT(*) AS anzahl, GROUP_CONCAT(kontakt_id ORDER BY kontakt_id) AS ids FROM kontakte GROUP BY email HAVING COUNT(*) > 1;
Achtung Kollation: Die Standard-Kollationen von MySQL/MariaDB vergleichen ohne Groß/Klein – dort landen „Anna.Berger@…“ und „anna.berger@…“ schon in derselben Gruppe.
SELECT email, COUNT(*) AS anzahl, STRING_AGG(CAST(kontakt_id AS varchar(10)), ',') WITHIN GROUP (ORDER BY kontakt_id) AS ids FROM kontakte GROUP BY email HAVING COUNT(*) > 1;
Übliche Server-Kollationen sind ebenfalls case-insensitive (…_CI_…).
SELECT email, COUNT(*) AS anzahl, LISTAGG(kontakt_id, ',') WITHIN GROUP (ORDER BY kontakt_id) AS ids FROM kontakte GROUP BY email HAVING COUNT(*) > 1;
SELECT email, COUNT(*) AS anzahl, GROUP_CONCAT(kontakt_id, ',') AS ids FROM kontakte GROUP BY email HAVING COUNT(*) > 1;
Textvergleich standardmäßig mit BINARY-Kollation: Groß/Klein zählt.
⚠️ Fallstricke
- „Duplikat“ ist eine fachliche Definition: gleiche E-Mail? gleicher Name und Ort? Jonas Feld aus Bonn (8) ist vielleicht umgezogen – oder eine andere Person.
- Ob
Anna.Berger@…undanna.berger@…gleich sind, entscheidet die Kollation – in SQLite und PostgreSQL nein, in den Standard-Kollationen von MySQL und SQL Server ja.
📚 Belege
- SQLite: Window Functions – Window Functions seit 3.25.0, ROWS/RANGE
- SQL Server: STRING_AGG – STRING_AGG seit 2017 (14.x)