Comment puis-jedelete duplicate rows
où aucun unique row id
n'existe?
Ma table est
col1 col2 col3 col4 col5 col6 col7
john 1 1 1 1 1 1
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
sally 2 2 2 2 2 2
Je souhaite conserver les éléments suivants après la suppression de la copie:
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
J'ai essayé quelques requêtes mais je pense qu'elles dépendent d'un identifiant de ligne car je n'obtiens pas le résultat souhaité. Par exemple:
DELETE FROM table WHERE col1 IN (
SELECT id FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)
J'aime les CTE et ROW_NUMBER
car les deux combinés nous permettent de voir quelles lignes sont supprimées (ou mises à jour), il suffit donc de changer le DELETE FROM CTE...
en SELECT * FROM CTE
:
WITH CTE AS(
SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7],
RN = ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col1)
FROM dbo.Table1
)
DELETE FROM CTE WHERE RN > 1
DEMO (le résultat est différent; je suppose que c'est dû à une faute de frappe de votre part)
COL1 COL2 COL3 COL4 COL5 COL6 COL7
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
Cet exemple détermine les doublons dans une colonne unique col1
en raison de PARTITION BY col1
. Si vous souhaitez inclure plusieurs colonnes, ajoutez-les simplement au PARTITION BY
:
ROW_NUMBER()OVER(PARTITION BY Col1, Col2, ... ORDER BY OrderColumn)
Je préférerais que CTE supprime les lignes en double de la table du serveur SQL
recommande vivement de suivre cet article :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/
en gardant l'original
WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)
DELETE FROM CTE WHERE RN<>1
sans garder l'original
WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)
Sans utiliser CTE
et ROW_NUMBER()
, vous pouvez simplement supprimer les enregistrements simplement en utilisant group by with MAX
et voici un exemple
DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
DELETE from search
where id not in (
select min(id) from search
group by url
having count(*)=1
union
SELECT min(id) FROM search
group by url
having count(*) > 1
)
Microsoft propose un guide très soigné sur la manière de supprimer les doublons. Départ http://support.Microsoft.com/kb/139444
En bref, voici le moyen le plus simple de supprimer des doublons lorsque vous n’avez que quelques lignes à supprimer:
SET rowcount 1;
DELETE FROM t1 WHERE myprimarykey=1;
myprimarykey est l'identifiant de la ligne.
J'ai réglé rowcount sur 1 car je n'avais que deux lignes dupliquées. Si j'avais dupliqué 3 lignes, j'aurais réglé rowcount sur 2 pour qu'il supprime les deux premières qu'il voit et n'en laisse qu'une dans la table t1.
J'espère que ça aide quelqu'un
S'il vous plaît voir le moyen de suppression ci-dessous aussi.
Declare @table table
(col1 varchar(10),col2 int,col3 int, col4 int, col5 int, col6 int, col7 int)
Insert into @table values
('john',1,1,1,1,1,1),
('john',1,1,1,1,1,1),
('sally',2,2,2,2,2,2),
('sally',2,2,2,2,2,2)
Crée un exemple de table nommé @table
et le charge avec les données données.
Delete aliasName from (
Select *,
ROW_NUMBER() over (Partition by col1,col2,col3,col4,col5,col6,col7 order by col1) as rowNumber
From @table) aliasName
Where rowNumber > 1
Select * from @table
Remarque: Si vous donnez toutes les colonnes dans la partie Partition by
, alors order by
n'aura pas beaucoup de signification.
Je sais, la question a été posée il y a trois ans et ma réponse est une autre version de ce que Tim a publié.
Après avoir essayé la solution suggérée ci-dessus, cela fonctionne pour les petites tables moyennes. Je peux suggérer cette solution pour les très grandes tables. puisqu'il fonctionne en itérations.
LargeSourceTable
sp_rename 'LargeSourceTable', 'LargeSourceTable_Temp'; GO
LargeSourceTable
, mais maintenant, ajoutez une clé primaire avec toutes les colonnes qui définissent les duplications. Ajoutez WITH (IGNORE_DUP_KEY = ON)
Par exemple:
CREATE TABLE [dbo].[LargeSourceTable]
(
ID int IDENTITY(1,1),
[CreateDate] DATETIME CONSTRAINT [DF_LargeSourceTable_CreateDate] DEFAULT (getdate()) NOT NULL,
[Column1] CHAR (36) NOT NULL,
[Column2] NVARCHAR (100) NOT NULL,
[Column3] CHAR (36) NOT NULL,
PRIMARY KEY (Column1, Column2) WITH (IGNORE_DUP_KEY = ON)
);
GO
Créez à nouveau les vues que vous avez déposées en premier lieu pour le nouveau tableau créé
Maintenant, exécutez le script SQL suivant, vous verrez les résultats dans 1 000 000 de lignes par page. Vous pouvez modifier le nombre de lignes par page pour afficher les résultats plus souvent.
Notez que je règle le IDENTITY_INSERT
sur et en dehors parce que l’une des colonnes contient un identifiant incrémentiel automatique, que je copie également.
SET IDENTITY_INSERT LargeSourceTable ON
DECLARE @PageNumber AS INT, @RowspPage AS INT
DECLARE @TotalRows AS INT
declare @dt varchar(19)
SET @PageNumber = 0
SET @RowspPage = 1000000
select @TotalRows = count (*) from LargeSourceTable_TEMP
While ((@PageNumber - 1) * @RowspPage < @TotalRows )
Begin
begin transaction tran_inner
; with cte as
(
SELECT * FROM LargeSourceTable_TEMP ORDER BY ID
OFFSET ((@PageNumber) * @RowspPage) ROWS
FETCH NEXT @RowspPage ROWS ONLY
)
INSERT INTO LargeSourceTable
(
ID
,[CreateDate]
,[Column1]
,[Column2]
,[Column3]
)
select
ID
,[CreateDate]
,[Column1]
,[Column2]
,[Column3]
from cte
commit transaction tran_inner
PRINT 'Page: ' + convert(varchar(10), @PageNumber)
PRINT 'Transfered: ' + convert(varchar(20), @PageNumber * @RowspPage)
PRINT 'Of: ' + convert(varchar(20), @TotalRows)
SELECT @dt = convert(varchar(19), getdate(), 121)
RAISERROR('Inserted on: %s', 0, 1, @dt) WITH NOWAIT
SET @PageNumber = @PageNumber + 1
End
SET IDENTITY_INSERT LargeSourceTable OFF
Si vous n'avez pas de références, comme des clés étrangères, vous pouvez le faire. Je le fais souvent lorsque je teste des preuves de concept et que les données de test sont dupliquées.
SELECT DISTINCT [col1], [col2], [col3], [col4], [col5], [col6], [col7]
INTO [newTable]
;
Allez dans l'explorateur d'objets et supprimez l'ancienne table.
Renommez la nouvelle table avec le nom de l'ancienne.
-- this query will keep only one instance of a duplicate record.
;WITH cte
AS (SELECT ROW_NUMBER() OVER (PARTITION BY col1, col2, col3-- based on what? --can be multiple columns
ORDER BY ( SELECT 0)) RN
FROM Mytable)
delete FROM cte
WHERE RN > 1
SELECT DISTINCT * FROM TABLE;
Cela supprimera toutes les lignes en double et ne vous fournira que les valeurs distinctes (lignes).
Si vous avez la possibilité d'ajouter temporairement une colonne à la table, voici une solution qui a fonctionné pour moi:
ALTER TABLE dbo.DUPPEDTABLE ADD RowID INT NOT NULL IDENTITY(1,1)
Puis effectuez un DELETE en combinant MIN et GROUP BY.
DELETE b
FROM dbo.DUPPEDTABLE b
WHERE b.RowID NOT IN (
SELECT MIN(RowID) AS RowID
FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
GROUP BY a.ITEM_NUMBER,
a.CHARACTERISTIC,
a.INTVALUE,
a.FLOATVALUE,
a.STRINGVALUE
);
Vérifiez que le DELETE a fonctionné correctement:
SELECT a.ITEM_NUMBER,
a.CHARACTERISTIC,
a.INTVALUE,
a.FLOATVALUE,
a.STRINGVALUE, COUNT(*)--MIN(RowID) AS RowID
FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
GROUP BY a.ITEM_NUMBER,
a.CHARACTERISTIC,
a.INTVALUE,
a.FLOATVALUE,
a.STRINGVALUE
ORDER BY COUNT(*) DESC
Le résultat ne doit pas contenir de lignes dont le nombre est supérieur à 1. Enfin, supprimez la colonne rowid:
ALTER TABLE dbo.DUPPEDTABLE DROP COLUMN RowID;
L’idée de supprimer les doublons implique
Pas à pas
with myCTE
as
(
select productName,ROW_NUMBER() over(PARTITION BY productName order by slno) as Duplicate from productDetails
)
Delete from myCTE where Duplicate>1
DECLARE @TB TABLE(NAME VARCHAR(100));
INSERT INTO @TB VALUES ('Red'),('Red'),('Green'),('Blue'),('White'),('White')
--**Delete by Rank**
;WITH CTE AS(SELECT NAME,DENSE_RANK() OVER (PARTITION BY NAME ORDER BY NEWID()) ID FROM @TB)
DELETE FROM CTE WHERE ID>1
SELECT NAME FROM @TB;
--**Delete by Row Number**
;WITH CTE AS(SELECT NAME,ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB)
DELETE FROM CTE WHERE ID>1;
SELECT NAME FROM @TB;
Vous devez regrouper les enregistrements en double en fonction du ou des champs, puis conserver l'un des enregistrements et supprimer le reste .
DELETE prg.Person WHERE Id IN (
SELECT dublicateRow.Id FROM
(
select MIN(Id) MinId, NationalCode
from prg.Person group by NationalCode having count(NationalCode ) > 1
) GroupSelect
JOIN prg.Person dublicateRow ON dublicateRow.NationalCode = GroupSelect.NationalCode
WHERE dublicateRow.Id <> GroupSelect.MinId)
La suppression de doublons d'une table énorme (plusieurs millions d'enregistrements) peut prendre un certain temps. Je suggère que vous fassiez une insertion en bloc dans une table temporaire des lignes sélectionnées plutôt que la suppression.
--REWRITING YOUR CODE(TAKE NOTE OF THE 3RD LINE) WITH CTE AS(SELECT NAME,ROW_NUMBER()
OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB) SELECT * INTO #unique_records FROM
CTE WHERE ID =1;
Oh wow, je me sens si bête de préparer toutes ces réponses, ce sont des réponses d’experts avec tous les tableaux CTE et Temp, etc.
Et tout ce que j'ai fait pour que cela fonctionne est simplement agrégé la colonne ID en utilisant MAX.
DELETE FROM table WHERE col1 IN (
SELECT MAX(id) FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)
REMARQUE: vous devrez peut-être l'exécuter plusieurs fois pour supprimer les doublons, car cela ne supprimera qu'un seul ensemble de lignes en double à la fois.
Pour ce faire, vous pouvez procéder de différentes manières sur SQL Server. La méthode la plus simple consiste à: insérer les différentes lignes de la table des lignes en double dans la nouvelle table temporaire. Supprimez ensuite toutes les données de la table de lignes en double, puis insérez toutes les données de la table temporaire ne contenant aucune copie, comme indiqué ci-dessous.
select distinct * into #tmp From table
delete from table
insert into table
select * from #tmp drop table #tmp
select * from table
Supprimer les lignes en double à l'aide de Common Table Expression (CTE)
With CTE_Duplicates as
(sélectionnez id, name, row_number () over (partition par id, nom par ordre, nom) numéro d'arrière-plan de la table) delete from CTE_Duplicates où rownumber! = 1
Une autre façon de supprimer les lignes en double sans perdre les informations en une étape est la suivante:
delete from dublicated_table t1 (nolock)
join (
select t2.dublicated_field
, min(len(t2.field_kept)) as min_field_kept
from dublicated_table t2 (nolock)
group by t2.dublicated_field having COUNT(*)>1
) t3
on t1.dublicated_field=t3.dublicated_field
and len(t1.field_kept)=t3.min_field_kept