У меня есть дубликаты в таблице, и я должен удалить их.
Почему?Пользователь может нажимать кнопки «Сохранить» или «Сохранить и закрыть», и из-за ошибки были клоны записи, когда он несколько раз нажимал кнопку «Сохранить».Типичная ситуация.
Пользователь может добавлять дубликаты в таблицу, но не чаще, чем один раз в час, сеанс с окном около 30 минут.
Другими словами - мы должны удалить записи, которые были созданы в + -30 минут.
Мне нужна помощь, могу ли я решить свою задачу без циклов (курсоров)?
Мои попытки и примеры данных:
declare @testData table(id int, createdOn datetime, val varchar(20))
insert into @testData(id, createdOn, val)
select 1, '2018-06-01 14:00:00' as CreatedOn, 'value1' as value1
union select 2, '2018-06-01 14:02:00', 'value1' -- duplicate
union select 3, '2018-06-01 14:04:00', 'value1' -- duplicate
union select 4, '2018-06-01 15:00:00', 'value2'
union select 5, '2018-06-01 15:02:00', 'value2' -- duplicate
union select 6, '2018-06-01 15:03:00', 'valueUniq1'
union select 7, '2018-06-01 15:04:00', 'valueUniq2'
union select 8, '2018-06-01 15:40:00', 'value2'
union select 9, '2018-06-01 15:41:00', 'valueUniq3'
union select 10, '2018-06-01 15:59:00', 'value1' -- NOT DUPLICATE!!!
union select 11, '2018-06-01 16:05:00', 'value1' -- duplicate
-- Option 1
;
with duplicates(IdDup, CreatedOnDup, valueDup)
as (
select a.Id, a.CreatedOn, a.val
from @testData a, @testData b
where a.id <> b.id
and a.val = b.val
and a.CreatedOn between dateadd(minute, -30, b.CreatedOn) and dateadd(minute, 30, b.CreatedOn)
)
select * from @testData
where Id in (
select IdDup
from duplicates)
and Id not in (
select min(IdDup)
from duplicates
group by valueDup)
-- Option 2
;
with duplicates(CounterDup, IdDup)
as (
select ROW_NUMBER() OVER(
Partition By
a.val
, cast(a.CreatedOn as date) -- Incorrect, must be +- 30 minutes, not the whole day
Order By a.Id ASC) As counterDup
, a.Id as idDup
from @testData a, @testData b
where a.id <> b.id
and a.val = b.val
and a.CreatedOn between dateadd(minute, -30, b.CreatedOn) and dateadd(minute, 30, b.CreatedOn)
)
select * from @testData
where Id in (
select IdDup
from duplicates
where CounterDup > 1)
and Id not in (
select IdDup
from duplicates
where CounterDup = 1)
Оба подхода возвращаютсяте же результаты, строки для удаления (дубликаты):
2 2018-06-01 14:02:00.000 value1
3 2018-06-01 14:04:00.000 value1
5 2018-06-01 15:02:00.000 value2
10 2018-06-01 15:59:00.000 value1
11 2018-06-01 16:05:00.000 value1
Предпоследняя строка не должна быть в наборе результатов.
10 2018-06-01 15:59:00.000 value1
Это не дубликат, это новый сеанс,потому что> 30 минут после предыдущего "value1".