2010-07-27 19 views
7

dire che ho righe duplicate nel mio tavolo e bene il mio progettazione del database è di 3 ° classe: -come eliminare completamente le righe duplicate

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

Voglio solo 1 istanza di ogni riga deve essere presente nel mio tavolo. Quindi 2nd, 3rd and last row che sono completamente identici dovrebbero essere cancellati. Quale query posso scrivere per questo? Può essere fatto senza creare tabelle temporanee? Solo in una singola query?

Grazie in anticipo :)

+0

Il primo record basata su ordine di inserimento? Per quale versione di SQL Server? –

+0

Sql Server 2008. – TCM

+0

Indovino che intendi la 3a forma normale quando dici 3a classe. Se consente duplicati completi in una tabella, non è in 3NF per definizione;) –

risposta

18

Prova questo - sarà eliminare tutti i duplicati dal vostro tavolo:

;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 

i duplicati dovrebbero essere più visibili: output è:

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

+0

Nice Marc_s, questa è una query CTE? In tal caso, non è necessario che la query CTE abbia una clausola 'union'? – TCM

+0

@Nitesh Panchal: sì, le CTE sono una delle funzionalità poco utilizzate di SQL Server - come la clausola OVER() :-) –

0

Primo utilizzo di un SELECT... INTO:

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

La goccia la prima tabella.

+5

Dall'OP: "Può essere eseguito senza creare tabelle temporanee? Solo in una singola query?" – 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 

rubato da How can I remove duplicate rows?

UPDATE:

Questo funziona solo se ProductId è una chiave primaria (che non è). Stai meglio usando il metodo di @marc_s, ma lascerò tutto questo nel caso in cui qualcuno che usa un PK trovi questo post.

+1

@Abe: 'rowid' era la chiave primaria per la tabella; Ho pensato che questa fosse la sintassi di Oracle per un momento finché non ho visto il collegamento. –

+0

Stavo partendo dal presupposto che ProductId fosse una chiave primaria nella sua tabella. L'ho aggiornato con i nomi delle sue colonne per evitare ogni confusione. –

+0

Nice Abe Miessler. Votato – TCM

1

Ho dovuto fare questo alcune settimane fa ... quale versione di SQL Server stai usando? In SQL Server 2005 e fino, è possibile utilizzare ROW_NUMBER come parte del vostro prescelto, e selezionare solo dove ROW_NUMBER è 1. I dimenticare la sintassi esatta, ma è ben documentato ... qualcosa sulla falsariga di:

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 

Check out http://msdn.microsoft.com/en-us/library/ms186734.aspx, che dovrebbe farti andare nella giusta direzione.

+1

Vero, ma l'OP ha bisogno di un'istruzione DELETE ... –

+0

@OMG Ponies - Er, buon punto. – BenAlabaster

+0

+1 Ben anche se .. – TCM

Problemi correlati