Nie powiedziałeś, jakiej wersji używasz, ale w SQL 2005 i nowszych wersjach możesz użyć wspólnego wyrażenia tabelowego z klauzulą OVER. To wygląda mniej więcej tak:
WITH cte AS (
SELECT[foo], [bar],
row_number() OVER(PARTITION BY foo, bar ORDER BY baz) AS [rn]
FROM TABLE
)
DELETE cte WHERE [rn] > 1
Pobaw się nim i zobacz, co otrzymasz.
(Edytuj:chcąc być pomocnym, ktoś zmodyfikował ORDER BY
klauzuli w CTE. Żeby było jasne, możesz tutaj zamówić według czego chcesz, nie musi to być jedna z kolumn zwracanych przez cte. W rzeczywistości częstym przypadkiem użycia jest tutaj to, że „foo, bar” to identyfikator grupy, a „baz” to swego rodzaju znacznik czasu. Aby zachować najświeższe informacje, wykonaj ORDER BY baz desc
)