1

使用了游标,但它很慢并且似乎是 SQL 作业中的一个大瓶颈。基本上,这是一项清理工作,从以前按产品 ID 和帐户可见性分组的特定来源中删除除前 X 配件(按销售排名排序)之外的所有配件。

该命令基本上是在游标循环的每次迭代中构建并exec手动编辑的。

vis列指的是多个租户,其行为类似于位掩码,例如两个租户可能拥有相同的产品。

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 回答