Я написал этот сценарий T-SQL для скручивания дублирующихся строк в базе данных, созданных в процессе реконструкции.Для этого он выполняет следующие действия:
- Получает и сохраняет минимальный первичный ключ целевой таблицы (ColTargetPK) для набора повторяющихся записей в табличной переменной (@minColTargetPKTable);определение дубликатов путем сопоставления по трем столбцам - ColIntA, ColIntB и ColDateTimeA.
- Устанавливает столбец назначения, который будет свернут (TargetColVarchar), равным объединению целевого столбца соответствующих повторяющихся записей.
- Помечает дубликаты записей как неактивные (ColTargetStatus = 0)
- Сообщает об успехе (или сбое)
Из-за размера используемого набора данных этот сценарий занимает неподходящее времябежать.
Может кто-нибудь увидеть, как это можно преобразовать в наборы, если да, не могли бы вы привести пример?
Заранее извиняюсь, если мое описание немного сбивает с толку ...
declare @MinColTargetPKTable table
(ColIntA int,
ColIntB int,
ColDateTimeA nvarchar(25),
minColTargetPK int
)
insert @minColTargetPKtable
select ColIntA, ColIntB, convert(nvarchar(25),ColDateTimeA,120) as ColDateTimeA,
min(ColTargetPK) as MinColTargetPK from TargetColTable
group by ColIntA, ColIntB, convert(nvarchar(25),ColDateTimeA,120)
declare @TargetColVarchar varchar(max)
declare @updatedColTargetPKs table
(updatedColTargetPKs int)
declare @minColTargetPK int
declare cur cursor
for
select minColTargetPK
from @minColTargetPKtable
open cur
fetch next from cur into @minColTargetPK
while @@FETCH_STATUS = 0
begin
begin try
set @TargetColVarchar =
convert(nvarchar(max),(
select replace(convert(nvarchar(max), isnull(TargetColVarchar,'')) + convert (nvarchar(max),' \par \par \par'), '\par } ', '\par') as
TargetColVarchar
from TargetColTable v1
where ColIntA = (select ColIntA from TargetColTable where ColTargetPK = @minColTargetPK)
and ColIntB = (select ColIntB from TargetColTable where ColTargetPK = @minColTargetPK)
and convert(nvarchar(25),ColDateTimeA,120) = (select convert(nvarchar(25),ColDateTimeA,120) from TargetColTable where ColTargetPK = @minColTargetPK)
order by ColTargetPK
for xml path(''), type
))
set @TargetColVarchar = REPLACE(REPLACE (REPLACE (@TargetColVarchar,'<TargetColVarchar>',''),'</TargetColVarchar>',''), '
','')
update TargetColTable
set TargetColVarchar = @TargetColVarchar
where ColTargetPK = @minColTargetPK
update TargetColTable
set ColTargetStatus = 0
from TargetColTable v1
where ColIntA = (select ColIntA from TargetColTable where ColTargetPK = @minColTargetPK)
and ColIntB = (select ColIntB from TargetColTable where ColTargetPK = @minColTargetPK)
and convert(nvarchar(25),ColDateTimeA,120) = (select convert(nvarchar(25),ColDateTimeA,120) from TargetColTable where ColTargetPK = @minColTargetPK)
and ColTargetPK != @minColTargetPK
Print 'Merge complete for ColTargetPK '+ convert(varchar(50), @minColTargetPK)
end try
begin catch
Print 'Merge failed for ColTargetPK '+ convert (varchar(20),@minColTargetPK)
end catch
fetch next from cur into @minColTargetPK
end
close cur
deallocate cur
РЕДАКТИРОВАТЬ: Хорошо, ниже приведен сценарий, перемещенный в операцию на основе набора по предложению Преета.Чтобы дать некоторый дополнительный фон, TargetTable составляет приблизительно 1,1 миллиона строк.Как ни странно, приведенный ниже сценарий на основе наборов не является значительно более быстрым, чем сценарий на основе курсора, приведенный ниже, в одном и том же подмножестве данных (около 20000 строк) в течение 2 испытаний.Любые мысли о том, почему это не будет быстрее?
declare @minColTargetPKTable table
(
ColIntA int,
ColIntB int,
ColDateTimeA nvarchar(25),
ColTargetPK int,
concTargetCol varchar(max)
)
insert @minColTargetPKtable (minColIntA,ColIntB,minColDateTimeA,minColTargetPK)
select ColIntA, ColIntB, convert(nvarchar(25),ColDateTimeA,120) as ColDateTimeA, min(ColTargetPK) as minColTargetPK from TargetTable
group by ColIntA, ColIntB, convert(nvarchar(25),ColDateTimeA,120)
update @minColTargetPKTable
set concTargetCol =
(REPLACE(REPLACE(REPLACE(replace(convert(nvarchar(max),
(
select convert(nvarchar(max), isnull(TargetColVarchar,'')) + convert (nvarchar(max),' \par \par \par ') as
TargetColVarchar
from TargetTable v1
where ColIntA = (select ColIntA from TargetTable where ColTargetPK = minColTargetPK)
and ColIntB = (select ColIntB from TargetTable where ColTargetPK = minColTargetPK)
and convert(nvarchar(25),ColDateTimeA,120) = (select convert(nvarchar(25),ColDateTimeA,120) from TargetTable where ColTargetPK = minColTargetPK)
order by ColTargetPK
for xml path(''), type
))
, '\par } ', '\par '),'<TargetColVarchar>',''),'</TargetColVarchar>',''), '
',''))
update TargetTable
set TargetColVarchar = mv.concTargetCol
from @minColTargetPKTable mv
where mv.minColTargetPK = TargetTable.ColTargetPK
update TargetTable
set TargetColStatus = 0
from TargetTable v
inner join @minColTargetPKTable mv on
mv.minColIntA = v.ColIntA
and mv.minColDateTimeA = convert(nvarchar(25),v.ColDateTimeA,120)
and mv.ColIntB = v.ColIntB
where ColTargetPK not in (select minColTargetPK from @minColTargetPKTable)