Voici une façon qui semble que cela devrait fonctionner pour vous.
Quelques hypothèses:
- Je suppose en double est une double rangée réelle hors ID, sur la base de 1 seconde clause que vous avez fourni. Si ce n'est pas le cas ... supprimez la partition par une partie de la fonction de fenêtre
row_number()
et cela changera le comportement
- Cela supprime les doublons récursifs. Autrement dit, si 3,4 ou même 15 lignes sont dans une seconde de l'autre, il garde 1.
- Cela devrait fonctionner, peu importe si la première ligne ou la dernière ligne est un double
Voici le code . Décommenter les deux lignes de la table pour voir les changements
declare @table table(id int, var1 int, var2 int, var3 int, date datetime2)
insert into @table
values
--(0,1,2,3,'2001-01-01 00:01:01.456'),
(1,1,2,3,'2001-01-01 01:01:01.456'), --dupe of 1/2/3
(2,1,2,3,'2001-01-01 01:01:02.214'), --dupe of 1/2/3
(3,1,2,3,'2001-01-01 01:01:02.234'), --dupe of 1/2/3
(4,1,2,3,'2001-01-01 01:01:02.244'), --dupe of 1/2/3
(5,1,2,3,'2001-01-01 01:01:04.789'), --dupe of 4/5
(6,1,2,3,'2001-01-01 01:01:04.989'), --dupe of 4/5
--(7,1,2,3,'2001-01-01 01:01:06.789'), --dupe of 6/7
(8,1,2,3,'2001-01-01 01:01:06.799') --dupe of 6/7
--apply the sequence
;with cte as(
select
*,
ROW_NUMBER() over (partition by var1, var2, var3 order by date) as RN --just in case... change this to just order by id, date if need be and remove the partition
from
@table),
--get first/most of the batch to remove
cte2 as(
select
c1.*
,c2.RN as RowsToRemove
from cte c1
left join
cte c2 on c1.RN < c2.rn and
datediff(second,c1.date,c2.date) < 1),
--remove the rows identified in the above cte
cte3 as(
select distinct
ID,
var1,
var2,
var3,
date,
RN
from cte2
where
RN not in (select distinct isnull(RowsToRemove,0) from cte2)),
--add another sequence. This is necessary for first/last row check for duplicate
cte4 as(
select
f.*,
row_number() over (partition by var1, var2, var3 order by date) RN2
from
cte3 f)
--return the results
select
f.ID,
f.var1,
f.var2,
f.var3,
f.date
from
cte4 f
left join
cte4 d on d.RN = f.RN - 1
where isnull(datediff(second,d.date,f.date),500) > 1
RETOURS
+----+------+------+------+-----------------------------+
| ID | var1 | var2 | var3 | date |
+----+------+------+------+-----------------------------+
| 1 | 1 | 2 | 3 | 2001-01-01 01:01:01.4560000 |
| 5 | 1 | 2 | 3 | 2001-01-01 01:01:04.7890000 |
| 8 | 1 | 2 | 3 | 2001-01-01 01:01:06.7990000 |
+----+------+------+------+-----------------------------+
s'il y a trois enregistrement dans une seconde de l'autre ... TENIR 1? et ID est juste un PK, ce qui signifie que var1, var2 et var3 devraient être considérés pour les doublons? c'est-à-dire s'ils ne sont pas identiques, alors ce n'est pas un doublon? – scsimon
@scsimon Oui. Tous les enregistrements où var1, 2 et 3 sont identiques et la date est dans 1 seconde, seul 1 enregistrement doit être conservé. Peu importe s'il y en a 2 ou 200 dans cette gamme. Id est un PK. – RossD
Merci pour la clarification @RossD. Je viens d'éditer ma réponse et je * thin * ça devrait marcher dans tous les cas. laissez-moi savoir si ce n'est pas le cas. Je l'ai laissé dans plusieurs cte pour plus de clarté. – scsimon