2010-07-27 54 views
7

Giả sử tôi có hàng trùng lặp trong bảng của tôi và cũng thiết kế cơ sở dữ liệu của tôi là của lớp 3: -Làm thế nào để xóa hoàn toàn trùng lặp hàng

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

tôi muốn chỉ có 1 thể hiện của mỗi hàng phải có mặt trong bảng của tôi. Vì vậy, 2nd, 3rd and last row whcih hoàn toàn giống hệt nhau nên bị xóa. Tôi có thể viết truy vấn nào cho điều này? Nó có thể được thực hiện mà không cần tạo các bảng tạm thời không? Chỉ trong một truy vấn duy nhất?

Cảm ơn trước :)

+0

Kỷ lục đầu tiên dựa trên trật tự chèn? Đối với phiên bản SQL Server nào? –

+0

Sql Server 2008. – TCM

+0

Tôi sẽ đoán rằng bạn có nghĩa là hình thức bình thường thứ 3 khi bạn nói lớp thứ ba. Nếu nó cho phép trùng lặp hoàn toàn trong một bảng, nó không phải trong 3NF theo định nghĩa;) –

Trả lời

18

Hãy thử điều này - nó sẽ xóa tất cả các bản sao từ bảng của bạn:

;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 

bản sao của bạn nên được đi ngay bây giờ: sản lượng là:

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

+0

Nice Marc_s, đây có phải là truy vấn CTE không? Nếu vậy, nó không cần thiết trong truy vấn CTE để có một mệnh đề 'union'? – TCM

+0

@Nitesh Panchal: có, CTE là một trong những tính năng không được sử dụng của SQL Server - như là mệnh đề OVER() :-) –

0

sử dụng đầu tiên một SELECT... INTO:

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

Sự sụt giảm bảng đầu tiên.

+5

Từ OP: "Nó có thể được thực hiện mà không cần tạo bảng tạm thời? Chỉ trong một truy vấn đơn?" – 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 

bị đánh cắp từ How can I remove duplicate rows?

UPDATE:

này sẽ chỉ làm việc nếu ProductID là một Primary Key (mà nó không phải là). Bạn nên sử dụng phương pháp @marc_s 'hơn, nhưng tôi sẽ bỏ qua điều này trong trường hợp ai đó sử dụng PK đi qua bài đăng này.

+1

@Abe: 'rowid' là khóa chính cho bảng; Tôi nghĩ rằng đây là cú pháp Oracle trong một thời gian cho đến khi tôi nhìn thấy liên kết. –

+0

Tôi đã giả định rằng ProductId là một khóa chính trong bảng của mình. Tôi đã cập nhật nó với tên cột của anh ấy để giúp tránh bất kỳ sự nhầm lẫn nào. –

+0

Nice Abe Miessler. Đã bình chọn – TCM

1

Tôi phải thực hiện việc này vài tuần trước ... bạn đang sử dụng phiên bản SQL Server nào? Trong SQL Server 2005 trở lên, bạn có thể sử dụng Row_Number như một phần của lựa chọn của bạn, và chỉ chọn nơi Row_Number là 1. Tôi quên cú pháp chính xác, nhưng nó cũng được ghi lại ... một cái gì đó dọc theo dòng:

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 

Kiểm tra http://msdn.microsoft.com/en-us/library/ms186734.aspx, điều đó sẽ giúp bạn đi đúng hướng.

+1

Đúng, nhưng OP cần một tuyên bố DELETE ... –

+0

@OMG Ngựa vằn - Er, điểm tốt. – BenAlabaster

+0

+1 Ben mặc dù .. – TCM

Các vấn đề liên quan