Ein anderer möglicher Weg, dies zu tun, ist
;
--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3
ORDER BY ( SELECT 0)) RN
FROM #MyTable)
DELETE FROM cte
WHERE RN > 1;
ich benutze ORDER BY (SELECT 0)
oben, da es beliebig ist, welche Zeile im Falle eines Unentschieden beibehalten werden soll.
Um die neueste zu erhalten, können RowID
Sie sie beispielsweise verwendenORDER BY RowID DESC
Ausführungspläne
Der Ausführungsplan hierfür ist häufig einfacher und effizienter als der in der akzeptierten Antwort, da keine Selbstverbindung erforderlich ist.
Dies ist jedoch nicht immer der Fall. Ein Ort, an dem die GROUP BY
Lösung bevorzugt werden könnte, sind Situationen, in denen ein Hash-Aggregat einem Stream-Aggregat vorgezogen wird .
Die ROW_NUMBER
Lösung wird immer fast den gleichen Plan geben, während die GROUP BY
Strategie flexibler ist.
Faktoren, die den Hash-Aggregat-Ansatz begünstigen könnten, wären
- Kein nützlicher Index für die Partitionierungsspalten
- relativ weniger Gruppen mit relativ mehr Duplikaten in jeder Gruppe
In extremen Versionen dieses zweiten Falls (wenn es nur sehr wenige Gruppen mit jeweils vielen Duplikaten gibt) könnte man auch in Betracht ziehen, einfach die Zeilen einzufügen, um sie in einer neuen Tabelle zu behalten, dann TRUNCATE
das Original zu kopieren und sie zurück zu kopieren, um die Protokollierung im Vergleich zum Löschen von a zu minimieren sehr hoher Anteil der Reihen.
DELETE FROM
CTE-Begriff direkt verwenden können. Siehe stackoverflow.com/q/18439054/398670