2010-07-27 17 views
7

że mam zduplikowane wiersze w moim stole i dobrze mój projekt bazy danych z 3 klasy: -Jak całkowicie usunąć zduplikowane wiersze

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

Chcę tylko 1 przypadek każdego wiersza powinny być obecne w moim stole. Tak więc 2nd, 3rd and last row, które są całkowicie identyczne, powinny zostać usunięte. Jakie zapytanie mogę o tym napisać? Czy można to zrobić bez tworzenia tabel tymczasowych? Tylko w jednym zapytaniu?

góry dzięki :)

+0

pierwszego rekordu na podstawie kolejności wstawiania? Do jakiej wersji serwera SQL? –

+0

Sql Server 2008. – TCM

+0

Zgaduję, że masz na myśli trzecią normalną formę, kiedy mówisz 3 klasę. Jeśli pozwala na pełne duplikaty w tabeli, to z definicji nie jest to 3NF;) –

Odpowiedz

18

Spróbuj tego - będzie usunąć wszystkie duplikaty z tabeli:

;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 

duplikaty należy już teraz: wyjście jest:

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 - pobity –

+0

Nice Marc_s, czy jest to zapytanie CTE? Jeśli tak, to czy w zapytaniu CTE nie jest konieczne posiadanie klauzuli "union"? – TCM

+0

@Nitesh Panchal: tak, CTE są jedną z niedostatecznie wykorzystywanych funkcji SQL Server - tak jak klauzula OVER() :-) –

0

najpierw użyć SELECT... INTO:

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

spadku pierwsza tabela.

+5

Z PO: "Czy można to zrobić bez tworzenia tabel tymczasowych? Tylko w jednym zapytaniu?" – 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 

skradzione How can I remove duplicate rows?

UPDATE:

To będzie działać tylko wtedy, gdy ProductId jest kluczem podstawowym (co nie jest). Lepiej jest użyć metody @marc_s, ale zostawię to na wypadek, gdyby ktoś używający PK natknął się na ten post.

+1

@Abe: 'rowid' był kluczem podstawowym dla tabeli; Myślałem, że to jest składnia Oracle na chwilę, dopóki nie zobaczyłem linku. –

+0

Zakładałem, że ProductId był kluczem podstawowym w swoim stole. Zaktualizowałem go jego nazwami kolumn, aby uniknąć zamieszania. –

+0

Nice Abe Miessler. Głosowało – TCM

1

Musiałem to zrobić kilka tygodni temu ... jakiej wersji SQL Server używasz? W SQL Server 2005 iw górę, można użyć row_number jako część select, a jedynie wybrać gdzie row_number to 1. Nie pamiętam dokładnej składni, ale jest dobrze udokumentowane ... coś wzdłuż linii:

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 

Zapoznaj się z http://msdn.microsoft.com/en-us/library/ms186734.aspx, która powinna sprawić, że będziesz podążał we właściwym kierunku.

+1

To prawda, ale OP potrzebuje instrukcji DELETE ... –

+0

Kucyki z "Samiec" - Er, dobry punkt. – BenAlabaster

+0

+1 Ben though .. – TCM

Powiązane problemy