Si tiene dos registros DIFERENTES con la misma columna de Producto, puede SELECCIONAR los registros no deseados con algún criterio, p.
CREATE TABLE victims AS
SELECT MAX(entryDate) AS date, Product, COUNT(*) AS dups FROM ProductsTable WHERE ...
GROUP BY Product HAVING dups > 1;
Luego puede hacer una ELIMINACIÓN DE JUNTA entre ProductTable y Víctimas.
O también puede seleccionar Producto solamente, y luego hacer un DELETE para alguna otra condición JOIN, por ejemplo, tener un CustomerId no válido, o EntryDate NULL, o cualquier otra cosa. Esto funciona si sabe que hay una y solo una copia válida del Producto, y todas las demás son reconocibles por los datos no válidos.
Supongamos que en su lugar tiene registros IDENTICOS (o tiene idénticos y no idénticos, o puede tener varios engaños para algún producto y no sabe cuál). Ejecuta exactamente la misma consulta. Luego, ejecuta una consulta SELECT en ProductsTable y SELECT DISTINCT todos los productos que coinciden con los códigos de producto para ser deducidos, agrupando por Producto y eligiendo una función agregada adecuada para todos los campos (si es idéntico, cualquier agregado debería hacerlo. De lo contrario, generalmente intento MAX o MIN).Esto "guardará" exactamente una fila para cada producto.
En ese punto, ejecuta DELETE JOIN y elimina todos los productos duplicados. Luego, simplemente vuelva a importar el subconjunto guardado y deducido en la tabla principal.
Por supuesto, entre DELETE JOIN y INSERT SELECT, tendrá la base de datos en un estado inestable, con todos los productos con al menos un duplicado simplemente desapareció.
Otra forma que debe trabajar en MySQL:
-- Create an empty table
CREATE TABLE deduped AS SELECT * FROM ProductsTable WHERE false;
CREATE UNIQUE INDEX deduped_ndx ON deduped(Product);
-- DROP duplicate rows, Joe the Butcher's way
INSERT IGNORE INTO deduped SELECT * FROM ProductsTable;
ALTER TABLE ProductsTable RENAME TO ProductsBackup;
ALTER TABLE deduped RENAME TO ProductsTable;
-- TODO: Copy all indexes from ProductsTable on deduped.
NOTA: la forma anterior NO FUNCIONA si desea distinguir "buenos" y "registros duplicados no válidos". Solo funciona si tiene registros redundantes DUPLICADOS, o si no le importa qué fila guarda y la tira!
EDITAR: Es decir que "duplicados" tienen campos no válidos. En ese caso se puede modificar el anterior con un truco de clasificación:
SELECT * FROM ProductsTable ORDER BY Product, FieldWhichShouldNotBeNULL IS NULL;
Entonces, si usted tiene sólo una fila para el producto, todo muy bien, se pondrá seleccionado. Si tiene más, aquel para el cual (FieldWhichShouldNouldBeNull IS NULL) es FALSE (es decir, aquél en el que FieldWhichShouldNheBeverNull en realidad no es nulo como debería) se seleccionará primero y se insertará. Todos los demás rebotarán, silenciosamente debido a la cláusula IGNORE, en contra de la singularidad del Producto. No es una forma realmente bonita de hacerlo (¡y comprueba que no mezcle verdadero con falso en mi cláusula!), Pero debería funcionar.
EDITAR
en realidad más de una nueva respuesta
Esta es una tabla simple para ilustrar el problema
CREATE TABLE ProductTable (Product varchar(10), Description varchar(10));
INSERT INTO ProductTable VALUES ('CBPD10', 'C-Beam Prj');
INSERT INTO ProductTable VALUES ('CBPD11', 'C Proj Mk2');
INSERT INTO ProductTable VALUES ('CBPD12', 'C Proj Mk3');
No existe un índice todavía, y sin clave primaria. Todavía podríamos declarar el producto como clave principal.
Pero sucede algo malo. Entran dos nuevos registros, y ambos tienen una descripción NULL.
Sin embargo, el segundo es un producto válido ya que no sabíamos nada de CBPD14 hasta ahora, y por lo tanto, NO queremos perder este registro por completo. Nosotros do queremos deshacernos de la falsa CBPD10 sin embargo.
INSERT INTO ProductTable VALUES ('CBPD10', NULL);
INSERT INTO ProductTable VALUES ('CBPD14', NULL);
Un grosero Eliminar en ProductTable DONDE Descripción IS NULL está fuera de la cuestión, sería matar CBPD14 que no es un duplicado.
Así lo hacemos así. En primer lugar obtener la lista de duplicados:
SELECT Product, COUNT(*) AS Dups FROM ProductTable GROUP BY Product HAVING Dups > 1;
asumimos que: "Hay por lo menos un buen registro para cada conjunto de registros en mal estado".
Comprobamos esta suposición al postular lo contrario y consultarlo. Si todo es copacetic, esperamos que esta consulta no devuelva nada.
SELECT Dups.Product FROM ProductTable
RIGHT JOIN (SELECT Product, COUNT(*) AS Dups FROM ProductTable GROUP BY Product HAVING Dups > 1) AS Dups
ON (ProductTable.Product = Dups.Product
AND ProductTable.Description IS NOT NULL)
WHERE ProductTable.Description IS NULL;
Para verificar más, inserto dos registros que representan este modo de falla; ahora espero que la consulta anterior devuelva el nuevo código.
INSERT INTO ProductTable VALUES ("AC5", NULL), ("AC5", NULL);
Ahora la consulta "cheque" de hecho se regresa,
AC5
Por lo tanto, la generación de Dups se ve bien.
Procedo ahora a eliminar todos los registros duplicados que no son válidos. Si hay registros duplicados y válidos, se mantendrán duplicados a menos que se encuentre alguna condición, distinguiendo entre ellos un registro "bueno" y declarando a todos los demás como "no válidos" (tal vez repitiendo el procedimiento con un campo diferente que la Descripción).
Pero ay, hay un problema. Actualmente, no puede eliminar de una tabla y seleccionar de la misma tabla en una subconsulta (http://dev.mysql.com/doc/refman/5.0/en/delete.html). Por lo tanto se necesita un poco de solución:
CREATE TEMPORARY TABLE Dups AS
SELECT Product, COUNT(*) AS Duplicates
FROM ProductTable GROUP BY Product HAVING Duplicates > 1;
DELETE ProductTable FROM ProductTable JOIN Dups USING (Product)
WHERE Description IS NULL;
Ahora bien, esto borrará todos los registros no válidos, siempre que aparecen en la tabla Dups.
Por lo tanto nuestro registro CBPD14 se deja intacto, ya que no aparece allí. El "buen" registro para CBPD10 quedará intacto porque no es cierto que su Descripción es NULL. Todos los demás - poof.
permítanme decir una vez más que si un registro tiene no registros válidos y aúnes un duplicado, a continuación, todas las copias de ese registro serán matados - no habrá sobrevivientes.
Para evitar esto, primero puede SELECCIONAR (utilizando la consulta anterior, la comprobación "que no debería devolver nada") las filas que representan este modo de falla en otra TABLA TEMPORAL, luego INSERTARlas nuevamente en la tabla principal después de la eliminación (usar transacciones podría estar en orden).
¿Qué tan grande es la base de datos. ¿Estamos hablando de millones de filas aquí? Miles de millones? –
aproximadamente 200,000 registros con 3000 duplicados, no mucho: D – Sypress
Cuando tiene dos registros con los mismos datos para Producto, pero datos diferentes en otras columnas, ¿cómo sabe cuál es el correcto para conservar? –