Just to give physical representation of Kenny's suggestions...
--===== Create a temporary demonstration table and populate it with duplicated info
-- This is not part of the solution... it's just creating a demo.
-- This DROP is just to support reruns for test purposes
IF OBJECT_ID('tempdb..#DuplicateVals') IS NOT NULL
DROP TABLE #DuplicateVals
CREATE TABLE #DuplicateVals
(
Col1VARCHAR(3),
Col2VARCHAR(3),
Col3VARCHAR(3)
)
INSERT INTO #DuplicateVals
(Col1,Col2,Col3)
SELECT 'aa1','aa1','aa1' UNION ALL --More than 1 duplicate from here...
SELECT 'aa1','aa1','aa1' UNION ALL
SELECT 'aa1','aa1','aa1' UNION ALL
SELECT 'aa1','aa1','aa1' UNION ALL
SELECT 'aa1','aa1','aa1' UNION ALL
SELECT 'aa1','aa1','aa1' UNION ALL --... to here
SELECT 'aa2','aa2','aa2' UNION ALL
SELECT 'aa2','aa2','aa2' UNION ALL
SELECT 'aa3','aa3','aa3' UNION ALL --No duplicates. Will it survive?
SELECT 'aa4','aa4','aa4' UNION ALL
SELECT 'aa4','aa4','aa4' UNION ALL
SELECT 'aa5','aa5','aa5' UNION ALL --No duplicates. Will it survive?
SELECT 'aa6','aa6','aa6' UNION ALL --More than 1 duplicate from here...
SELECT 'aa6','aa6','aa6' UNION ALL
SELECT 'aa6','aa6','aa6' --... to here
--===== Sanity check: Display the contents of the test table BEFORE the deletion
SELECT * FROM #DuplicateVals
--===== Delete duplicates without any temporal information present.
-- Note that there isn't actually any reason to return any columns from the table in the CTE...
-- Just the RowNum will suffice.
;WITH cteDV AS
(
SELECTROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 ORDER BY Col1, Col2, Col3 ) AS RowNum
FROM#DuplicateVals
)
DELETE FROM cteDV WHERE RowNum > 1
--===== Sanity check: Display the contents of the test table AFTER the deletion
SELECT * FROM #DuplicateVals
... the details are in the code but I wanted to point out that you don't really need to return any of the table's columns in the CTE for this method to work... just the RowNum.
--Jeff Moden
Change is inevitable... Change for the better is not.