2010-07-27 106 views
7

说我有重复行我表以及我的数据库设计是第三类: -如何彻底删除重复的行

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'); 

我只想要1每一行的情况下应该出现在我的表。因此应删除完全相同的2nd, 3rd and last row。我可以为此编写什么查询?可以在不创建临时表的情况下完成吗?只是在一个单一的查询?

感谢提前:)

+0

第一个记录基于插入顺序?对于什么版本的SQL Server? – 2010-07-27 15:41:02

+0

Sql Server 2008. – TCM 2010-07-27 15:42:41

+0

当你说第三课时,我会猜测你的意思是第三范式。如果它允许在一个表中完全重复,它不是按照定义3NF;) – 2010-07-27 15:47:38

回答

18

试试这个 - 它会从表中删除所有重复:

;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 

你的副本现在应该走了:输出为:

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 - 殴打 – 2010-07-27 15:55:53

+0

Nice Marc_s,这是CTE查询吗?如果是这样,CTE查询中没有必要有一个'union'子句? – TCM 2010-07-27 15:58:02

+0

@Nitesh Panchal:是的,CTE是SQL Server的未被使用的特性之一 - 就像OVER()子句一样:-) – 2010-07-27 15:59:29

0

首先使用SELECT... INTO

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

的下降的第一个表。

+5

从OP:“可以在没有创建临时表的情况下完成吗?只需一个查询?” – dcp 2010-07-27 15:38:32

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 

被盗从How can I remove duplicate rows?

UPDATE:

这如果ProductID等于主键(它不是)才有效。你最好使用@marc_s'方法,但是我会留下这个以防万一有人使用PK会遇到这篇文章。

+1

@Abe:'rowid'是表格的主键;我认为这是Oracle语法片刻,直到我看到链接。 – 2010-07-27 15:43:17

+0

我假设ProductId是他的表中的主键。我用他的专栏名称更新了它,以帮助避免任何混淆。 – 2010-07-27 16:01:55

+0

尼斯安倍Miessler。投票 – TCM 2010-07-27 16:06:43

1

我不得不在几个星期前做这个......你正在使用什么版本的SQL Server?在SQL Server 2005和了,你可以使用ROW_NUMBER为您选择的一部分,并且只能选择其中ROW_NUMBER为1。我忘了确切的语法,但它是有据可查......沿着线的东西:

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 

退房http://msdn.microsoft.com/en-us/library/ms186734.aspx,这应该让你朝着正确的方向前进。

+1

是的,但OP需要DELETE语句... – 2010-07-27 15:46:16

+0

@OMG小马 - 呃,好点。 – BenAlabaster 2010-07-27 15:54:42

+0

+1 Ben虽然.. – TCM 2010-07-27 16:05:36