替代使用游标基于子查询更新数据库

问题描述 投票:0回答:3

也许这个头衔并不是真正的启发,但我不能用一个不那么做作的人来。这是我的问题:

我正在使用具有看起来像数据的表

id  cId        ver      active
1   100         1       0    
2   100         2       1    
3   100         3       1    
4   200         1       0    
5   200         2       1    
6   300         1       1

对于此表,Id是PK,cId标识客户端。基本上我们存储版本历史。

我试图解决的问题是更新数据库以仅为每个客户端最高[ver]的最新版本设置active = 1。 (示例中包含cId 100的客户端)

现在,我已设法编写以下查询,该查询为我提供了数据

select t.id, t.cId,t.version 
from (select *
      from comp.Clients  a
      where a.ver = (select max(b.ver) from comp.Clients b where a.cId=b.cIdentifier)
    ) t

从那时起,我的解决方案是将该查询插入游标上,对于游标上的每个记录,我会将表更新为active = 0,并将active = 1更新为当前记录。

事情是游标是它们是什么,有什么东西给我一个体面的表现在这里?我对CTE并不好,所以我无法想出一个围绕它的解决方案。实际表有大约10k记录和大约50个字段。

sql sql-server common-table-expression database-cursor
3个回答
1
投票

你应该找到每个ver的最后一个CId然后更新你的表

select cId,Max(ver) as MaxVer into #tmpTable from comp.Clients  group by cid

update c
set active = case when t.cId is not null then 1 else 0 end
from comp.Clients c left join #tmpTable t on t.CId=c.CId and t.MaxVer=c.ver

0
投票

而不是使用游标,使用2更新。一个用于将值更新为0,另一个用于将客户端ID的最新版本设置为1.这应该足够了。


0
投票

使用可更新的CTE:

with toupdate as (
      select c.*,
             max(ver) over (partition by CId) as max_ver
      from comp.Clients c
     )
update toupdate
    set active = (case when max_ver = ver then 1 else 0 end);

如果您愿意,可以添加where子句来限制要更新的行数:

   where active <> (case when max_ver = ver then 1 else 0 end)
© www.soinside.com 2019 - 2024. All rights reserved.