2010-07-27 12 views
7

decir que tengo las filas duplicadas en mi mesa y así mi diseño de base de datos es de tercera clase: -¿Cómo suprimir por completo las filas duplicadas

Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (1,'Cinthol','cosmetic soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (1,'Cinthol','cosmetic soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (1,'Cinthol','cosmetic soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (1,'Lux','cosmetic soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (1,'Crowning Glory','cosmetic soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (2,'Cinthol','nice soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (3,'Lux','nice soap','soap'); 
Insert Into tblProduct (ProductId,ProductName,Description,Category) Values (3,'Lux','nice soap','soap'); 

quiero a sólo 1 instancia de cada fila debe estar presente en mi mesa. Por lo tanto, 2nd, 3rd and last row que son completamente idénticos deben ser eliminados. ¿Qué consulta puedo escribir para esto? ¿Se puede hacer sin crear tablas temporales? Solo en una sola consulta?

Gracias de antemano :)

+0

El primer registro basa en orden de inserción? ¿Para qué versión de SQL Server? –

+0

Sql Server 2008. – TCM

+0

Voy a adivinar que te refieres a la 3ra forma normal cuando dices 3ra clase. Si permite duplicados completos en una tabla, no está en 3NF por definición;) –

Respuesta

18

Prueba esto - se eliminará todos los duplicados de la tabla:

;WITH duplicates AS 
(
    SELECT 
     ProductID, ProductName, Description, Category, 
     ROW_NUMBER() OVER (PARTITION BY ProductID, ProductName 
          ORDER BY ProductID) 'RowNum' 
    FROM dbo.tblProduct 
) 
DELETE FROM duplicates 
WHERE RowNum > 1 
GO 

SELECT * FROM dbo.tblProduct 
GO 

Sus duplicados deberían haber desaparecido ahora: la salida es:

ProductID ProductName DESCRIPTION  Category 
    1   Cinthol   cosmetic soap  soap 
    1   Lux    cosmetic soap  soap 
    1   Crowning Glory cosmetic soap  soap 
    2   Cinthol   nice soap   soap 
    3   Lux    nice soap   soap 
+2

+1: Drats - batido –

+0

Nice Marc_s, ¿esta es una consulta CTE? Si es así, ¿no es necesario en la consulta CTE tener una cláusula 'union'? – TCM

+0

@Nitesh Panchal: sí, los CTE son una de las características infrautilizadas de SQL Server, como lo es la cláusula OVER() :-) –

0

primer lugar el uso de un SELECT... INTO:

SELECT DISTINCT ProductID, ProductName, Description, Category 
    INTO tblProductClean 
    FROM tblProduct 

La caída de la primera tabla.

+5

Desde el OP: "¿Se puede hacer sin crear tablas temporales? ¿Solo en una sola consulta?" – dcp

4
DELETE tblProduct 
FROM tblProduct 
LEFT OUTER JOIN (
    SELECT MIN(ProductId) as ProductId, ProductName, Description, Category 
    FROM tblProduct 
    GROUP BY ProductName, Description, Category 
) as KeepRows ON 
    tblProduct.ProductId= KeepRows.ProductId 
WHERE 
    KeepRows.ProductId IS NULL 

Robados de How can I remove duplicate rows?

ACTUALIZACIÓN:

Esto sólo funcionará si ProductId es una clave principal (que no lo es). Es mejor que utilices el método de @marc_s, pero lo dejaré en caso de que alguien que use un PK se encuentre con esta publicación.

+1

@Abe: 'rowid' fue la clave principal para la tabla; Pensé que esta era la sintaxis de Oracle por un momento hasta que vi el enlace. –

+0

Estaba asumiendo que ProductId era una clave principal en su tabla. Lo he actualizado con sus nombres de columna para ayudar a evitar cualquier confusión. –

+0

Nice Abe Miessler. Votado – TCM

1

Tuve que hacer esto hace unas semanas ... ¿qué versión de SQL Server estás usando? En SQL Server 2005 y hasta, puede utilizar ROW_NUMBER como parte de su selecto, y sólo seleccionar dónde ROW_NUMBER es 1. olvido la sintaxis exacta, pero está bien documentado ... algo a lo largo de las líneas de:

Select t0.ProductID, 
     t0.ProductName, 
     t0.Description, 
     t0.Category 
Into tblCleanData 
From (
    Select ProductID, 
      ProductName, 
      Description, 
      Category, 
      Row_Number() Over (
       Partition By ProductID, 
          ProductName, 
          Description, 
          Category 
       Order By  ProductID, 
          ProductName, 
          Description, 
          Category 
      ) As RowNumber 
    From MyTable 
) As t0 
Where t0.RowNumber = 1 

Eche un vistazo a http://msdn.microsoft.com/en-us/library/ms186734.aspx, eso debería hacerlo avanzar en la dirección correcta.

+1

Cierto, pero el OP necesita una declaración DELETE ... –

+0

@OMG Ponies - Er, buen punto. – BenAlabaster

+0

+1 Ben aunque ... – TCM

Cuestiones relacionadas