1

カーソルが使用されますが、速度が遅く、SQLジョブの大きなボトルネックのように見えます。基本的に、これは、以前に製品IDとアカウントの可視性によってグループ化された特定のソースから上位X個のアクセサリ(販売ランク順に並べられたもの)を除くすべてを削除するためのクリーンアップ作業です。

このコマンドは基本的に、カーソルループの各反復に組み込まれ、exec手動で編集されます。

このvis列は、ビットマスクのように機能する複数のテナントを示しています。たとえば、2つのテナントが同じ製品を持っている可能性があります。

declare @prodid int
declare @cnt    int
declare @vis    bigint
declare @cmd    varchar(600)
declare @clause varchar(600)

-- find records with more than X excess accessories
declare cur cursor for
    select pa.prodid, 'cnt' = count(*), vis from [accessories] pa
    group by prodid, vis
    having count(*) > X -- e.g. 5

サンプル出力は次のようになります

prodid  cnt     vis
123     6       128
234     8       260
345     10      512

X = 5の場合、salesrank123の最後の1項目、234の最後の3項目、および345の最後の5項目が削除されます。これは、ネストされた選択にグループ化を含めながら、ステートメントを使用して実行できますか?DELETE

open cur

fetch next from cur into @prodid, @cnt, @vis
while @@fetch_status = 0
begin
    -- a clause that ends up looking like this:
    -- 12345 and vis = 128 -- OR -- 23456 and vis is null   
    set @clause = convert(varchar(14), @prodid) + ' and vis ' + case 
        when @vis is null then ' is null ' 
        else ' = ' + cast(@vis as varchar) end

    -- delete all but the top X from source=2 and that match prodid and vis
    set @cmd = 'delete from [accessories] 
        where source = 2 and prodid=' + @clause +
        ' and access_prodid in (select top ' + convert(varchar(5), @cnt - X) + 
        ' access_prodid from [accessories] where prodid = ' 
        + @clause + ' and source = 2 order by salesrank)'

    exec(@cmd)
    fetch next from cur into @prodid, @cnt, @vis
end 
close cur
deallocate cur
4

2 に答える 2

4

これを試して:

WITH DupData AS
(
    SELECT  *,
      ROW_NUMBER() 
          OVER(PARTITION BY pa.prodid, pa.vis ORDER BY salesrank) Position
      FROM [accessories] pa
      WHERE pa.source = 2
)
DELETE 
    FROM DupData
 WHERE Position > 5
于 2012-07-10T19:14:39.150 に答える
0

これを行うには、Windows関数を使用して、削除する行を識別します。

with t as (select pa.*,
                  row_number() over (partition by prodid, vis order b salesrank) as sr
           from [accessories] pa
          )
delete from pa
from t
where pa.prodid = t.prodid and pa.vis = t.vis and pa.salesrank = t.salesrank

paテーブルに一意のIDがある場合は、より複雑なwhereステートメントの代わりにそれを使用できます。これは、salesrankが各prodid/visグループ内で一意であることを前提としています。

于 2012-07-10T19:17:25.777 に答える