Note that there are some explanatory texts on larger screens.

plurals
  1. POCan this row-by-row T-SQL script be converted to a set-based script?
    primarykey
    data
    text
    <p>I have written this T-SQL script to roll up duplicate rows in a database that are created by a reconstruction process. To do this, it performs the following:</p> <ul> <li>Gets and stores the minimum target table primary key (ColTargetPK) per set of duplicate entries in a table variable (@minColTargetPKTable); determining duplicates by matching on three columns - ColIntA, ColIntB and ColDateTimeA.</li> <li>Sets the Target Column to be rolled up (TargetColVarchar) to equal a concatenation of the target column of the corresponding duplicate entries.</li> <li>Flags the duplicate entries as inactive (ColTargetStatus = 0)</li> <li>Reports success (or failure)</li> </ul> <p>Due to the size of the dataset involved, this script takes an inappopriate length of time to run. </p> <p>Can anyone see how this can be converted to be set-based, if so, could you please provide an example?</p> <p>I apologise in advance if my description is a bit confusing...</p> <pre><code>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,'&lt;TargetColVarchar&gt;',''),'&lt;/TargetColVarchar&gt;',''), '&amp;#x0D;','') 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 </code></pre> <p>EDIT: Ok, below is the script moved to a set-based operation using Preet's suggestion. To give some additional background, TargetTable is approximately 1.1 million rows. Strangely enough, the set-based script below is not significantly faster than the cursor-based script below on the same subset of data (approx. 20000 rows) over 2 trials. Any thoughts on why this wouldn't be faster?</p> <pre><code>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 '),'&lt;TargetColVarchar&gt;',''),'&lt;/TargetColVarchar&gt;',''), '&amp;#x0D;','')) 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) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload