Aquí os traigo unas cuantas versiones de como eliminar duplicados en una tabla con SQL. Me ha parecido interesante crear este blog porque en Internet hay muchas maneras, pero yo he desarrollado otra, que puede que no sea la más eficiente, pero desde luego creo que es la más rápida y fácil de implementar.
Los datos de ejemplo
Primero vamos a suponer una tabla en la que tenemos un montón de registros en los que todas las columnas tienen el mismo dato, menos una, o varias. Por lo que necesitamos eliminar todos los registros que tengan exactamente los mismos datos, o, como es mi caso, necesitamos solo un registro o una fila por cada columna que nos interesa no este duplicada.
En el ejemplo que os propongo es el siguiente. Tenemos una tabla que almacena códigos postales y transportistas, con el precio para cada código postal. El error en la tabla, se supone, cuando tenemos el mismo código postal en un mismo transportista con diferente precio.
código postal | transportista a utilizar | precio |
1234 | uno cualquiera | 10 |
1234 | uno cualquiera | 5 |
2345 | uno cualquiera | 10 |
3456 | uno cualquiera | 10 |
5678 | uno cualquiera | 10 |
2345 | uno cualquiera | 7 |
1234 | uno cualquiera | 15 |
Solución 1: la que he pensado yo
En mi caso me interesa seleccionar el precio más elevado y eliminar todas las demás filas que no necesito. Para ello hice una consulta seleccionando los campos que necesitaba y obteniendo el máximo valor de la columna precio. Luego con esta consulta almacenada en elimine de la tabla original todos los elementos que todas las columnas eran igual menos la del precio dentro de la otra consulta. Aquí el código:
with duplicados (PostCode,IdCourier, price)
as (SELECT DISTINCT PostCode, IdCourier, max(price)
FROM couriers_run
group by PostCode, IdCourier, price)
delete couriers_run
from duplicados
where couriers_run.price <> duplicados.price
and couriers_run.PostCode = duplicados.PostCode
and couriers_run.IdCourier = duplicados.IdCourier
Solución 2: la recomendada por Microsoft
Nuestro querido Microsoft nos recomienda crear una tabla temporal donde almacenar los duplicados, para luego eliminar de la tabla los elementos que están contenidos en la temporal, para luego eliminar la tabla temporal. Desde mi punto de vista, escribes más código, pero básicamente es lo mismo que hemos hecho antes. El código es:
SELECT DISTINCT * INTO duplicate_table
FROM original_table
GROUP BY key_value
HAVING COUNT(key_value) > 1
DELETE original_table
WHERE key_value
IN (SELECT key_value
FROM duplicate_table)
INSERT original_table
SELECT *
FROM duplicate_table
DROP TABLE duplicate_table
Solución 3: desde stackoverflow
En stackoverflow hay varios métodos también pero uno de los que más me gustó, por no tener que estar creando tablas temporales, es este que os dejo copio aquí. El autor es Juan Ruiz de Castilla.
DELETE A
FROM MyTable A
INNER JOIN
(
SELECT ROW_NUMBER()OVER(PARTITION BY a.col1,
a.Col2
ORDER BY a.Col1,a.Col2)AS POS,
a.rowID,
a.Col3
FROM MyTable A
JOIN
(
Select
Col1,
Col2,
COUNT(*) AS CONTADOR
from MyTable
group by Col1,
Col2
HAVING COUNT(*) > 1
) TB
ON A.col1 = TB.col1
AND A.col2 = TB.col2
) TB_2
ON
a.ROWID = tb_2.ROWID
and tb_2.pos > 1
Solución 4: por último lugar
Que incluya en el último lugar este otro método no quiere decir que sea el peor, todo lo contrario, me gustó mucho, pero realmente lo encontré el último y sencillamente estoy siguiendo, más o menos, el orden de cuando fui encontrando la información. Es más el autor de este método, Heliberto Arias, en su blog, también nos propone otro. En este caso también podemos realizar la eliminación sin necesidad de crear tablas temporales.
DELETE FROM dbo.post_history
WHERE post_history_id NOT IN(
SELECT PH.post_history_id
FROM(
SELECT PH.title
FROM dbo.post_history AS PH
GROUP BY PH.title) Titles
CROSS APPLY
(
SELECT TOP(1)
PH.post_history_id
FROM dbo.post_history AS PH
WHERE PH.title = Titles.title
ORDER BY PH.created_date ASC
) PH
);
Conclusiones
Aunque realmente no he cambiado las consultas que provienen de otras fuentes para comparar el número de lineas escritas con respecto de mi solución, creo que con mi solución se escriben menos líneas y es igual de eficiente. Espero que les guste esta información. Como siempre en los enlaces podrás encontrar las fuentes originales, reconociendo a los autores y sus fuentes.
Happy codding