sql >> Database teknologi >  >> RDS >> Sqlserver

Opdater alle undtagen én af duplikerede poster i tabel i SQL Server

Du kan løse dette problem uden en join, hvilket betyder, at det burde have bedre ydeevne. Ideen er at gruppere dataene efter dit object_id, og tælle rækkenummeret for hvert object_id. Dette er hvad "partition by" gør. Derefter kan du opdatere hvor rækken_numre er> 1. Dette vil opdatere alle duplikerede objekt_id undtagen den første!

update t set t.status_val = 'some_status' 
from (
    select *, row_number() over(partition by object_id order by (select null)) row_num  
    from foo
) t 
where row_num > 1 

På en testtabel med 82944 poster var ydeevnen sådan (din kilometertal kan variere!):Tabel 'test'. Scanning tæller 5, logisk læser 82283, fysisk læser 0, read-ahead læser 0, lob logisk læser 0, lob fysisk læser 0, lob read-ahead læser 0.CPU tid =141 ms, forløbet tid =150 ms.

Vi kan bestemt også løse dette problem ved at bruge en indre joinforbindelse, men generelt burde dette føre til mere logiske læsninger og højere CPU:

Tabel 'test'. Scanningsantal 10, logisk læser 83622, fysisk læser 0, read-ahead læser 0, lob logisk læser 0, lob fysisk læser 0, lob read-ahead læser 0. Tabel 'Workfile'. Scanningsantal 0, logisk læser 0, fysisk læser 0, read-ahead læser 0, lob logisk læser 0, lob fysisk læser 0, lob read-ahead læser 0.Tabel 'Arbejdstabel'. Scanning tæller 4, logisk læser 167426, fysisk læser 0, read-ahead læser 0, lob logisk læser 0, lob fysisk læser 0, lob read-ahead læser 0.CPU tid =342 ms, forløbet tid =233 ms.

Sådan går du over resultaterne og opdaterer i mindre partier:

declare @rowcount int = 1;
declare @batch_size int = 1000;

while @rowcount > 0 
begin
    update top(@batch_size) t set t.status_val = 'already updated'
    from (
        select *, row_number() over(partition by object_id order by (select null)) row_num  
        from foo
        where status_val <> 'already updated' 
    ) t 
    where row_num > 1 
    set @rowcount = @@rowcount;
end

Dette vil hjælpe med at blive ved med at låse ned, hvis andre samtidige sessioner forsøger at få adgang til denne tabel.



  1. Hvordan formindsker man temp tablespace i Oracle?

  2. MySQL - Konverter MM/DD/ÅÅ til Unix tidsstempel

  3. Sådan forbinder du Android til mysql-databasen sikkert

  4. Indsættelse af MySQL-resultater fra PHP i JavaScript Array