Một cách khác có thể làm điều này là
;
--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;
Tôi đang sử dụng ORDER BY (SELECT 0)
ở trên vì nó là tùy ý hàng nào để bảo quản trong trường hợp hòa.
Để bảo quản cái mới nhất RowID
để lấy ví dụ bạn có thể sử dụngORDER BY RowID DESC
Kế hoạch thực hiện
Kế hoạch thực hiện cho việc này thường đơn giản và hiệu quả hơn so với câu trả lời được chấp nhận vì nó không yêu cầu tự tham gia.
Điều này không phải lúc nào cũng đúng. Một nơi mà GROUP BY
giải pháp có thể được ưu tiên là các tình huống trong đó tổng hợp băm sẽ được chọn theo sở thích đối với tổng hợp luồng.
Các ROW_NUMBER
giải pháp sẽ luôn luôn cung cấp cho khá nhiều kế hoạch tương tự trong khi GROUP BY
chiến lược là linh hoạt hơn.
Các yếu tố có thể ủng hộ cách tiếp cận tổng hợp băm sẽ là
- Không có chỉ mục hữu ích trên các cột phân vùng
- các nhóm tương đối ít hơn với các bản sao tương đối nhiều hơn trong mỗi nhóm
Trong các phiên bản cực đoan của trường hợp thứ hai này (nếu có rất ít nhóm có nhiều nhóm trùng lặp), người ta cũng có thể xem xét đơn giản là chèn các hàng để giữ vào một bảng mới sau đó - TRUNCATE
sao chép bản gốc và sao chép chúng để giảm thiểu ghi nhật ký so với xóa tỷ lệ rất cao của các hàng.
DELETE FROM
trực tiếp sử dụng thuật ngữ CTE. Xem stackoverflow.com/q/18439054/398670