2

我有一个奇怪的更新查询要写。

这是桌子

PK-ID (int) --- FK-ID (int) --- Value (int)

在我的数据集中,如果我按 FK-ID 分组并按 PK-ID 排序,假设这是一组示例:

5 --- 10 --- 23
7 --- 10 --- 49
8 --- 10 --- 81

由于某些旧软件中的错误,记录 7 和 8 的值不正确。7 的正确值是 (49-23) = 26,8 的正确值是 (81-4​​9) = 32。记录 5 是正确的。

当它按 FK-ID 分组并按 PK-ID 排序时,我需要更新每条记录以减去它之前的记录的值。如果没有前面的记录,我不需要更改该值。

有没有办法编写一个通用的 sql 更新查询来完成这个?我将如何(有条件地)检索组中先前记录的值?我正在使用 SQL Server 2008。

谢谢!

4

4 回答 4

2
with ordered as (
    select *, rn = row_number() over (partition by fk_id order by pk_id)
      from tbl
    )
update cur
   set value = cur.value - prior.value
  from ordered cur
  join ordered prior on prior.fk_id = cur.fk_id
                and prior.rn = cur.rn-1;
于 2012-12-12T19:01:16.140 回答
2

这是我认为正确的答案,使用与前一个类似的想法。toupdate 子查询根据问题中的规则计算值(更新具有相同外键和连续主键的记录)。它确实假设 id 是某种数字值。

with toupdate as (
    select t.pkid, t.value - tprev.value as newval
    from t join
         t tprev
         on t.pkid = tprev.pkid+1 and t.fkid = tprev.fkid
   )
update t
    set value = newvalue
    from toupdate
    where t.pkid = toupdate.pkid
于 2012-12-12T19:38:22.683 回答
1

我希望它应该返回你想要的(对不起,我现在不能尝试);你只需要将它与UPDATE

 WITH cte1 AS 
 (SELECT pk_id, fk_id, value, ROW_NUMBER() OVER (PARTITION BY fk_id ORDER BY pk_id DESC)
 as num 
 FROM your_table 
 )

 SELECT a.*, 
 --CASE 
 --  WHEN b.pk_id IS NOT NULL THEN a.value-b.value 
 --  ELSE 0 END 
 a.value-b.value as valid_number
 FROM cte1 a
 --LEFT JOIN cte1 b ON (b.fk_id = a.fk_id AND b.num = a.num-1)
 INNER JOIN cte1 b ON (b.fk_id = a.fk_id AND b.num = a.num-1)  
于 2012-12-12T19:00:37.493 回答
1
update t set value = value -
              isnull((select top 1 value 
                                 from t t2 
                                     where t2.FKID=t.FKID 
                                       and t2.PKID<t.PKID 
                        order by PKID desc),0);

这是一个SQLFiddle 演示

于 2012-12-12T19:07:31.480 回答