SQL - 如果相应的值都相同,则用一个值更新字段

SQL - update field with a value, if corresponding values are all the same

我手头有一项有趣的任务,我正在想办法去做。

假设我在 table 中有以下数据:

  Num1      Acct      Amt         Type1       Type2        AmtX     AmtY    AcctBadInd
  X12       111       90           X          1            NULL     NULL    NULL
  X12       222       -90          X          1            NULL     NULL    NULL
  X12       333       90           X          1            NULL     NULL    NULL

  Y33       111       75           Y          1            NULL     NULL    NULL
  Y33       444       -75          Y          1            NULL     NULL    NULL

  Z44       111       55           Y          1            NULL     NULL    NULL
  Z44       111       55           Y          0            NULL     NULL    NULL
  Z44       444       -65          Y          1            NULL     NULL    NULL

下面是几个例子。唯一需要注意的是,给定的 Num1 可以有任意数量的记录,但总是 >= 2。因此它可能是 2、3、4、5,并且相同的逻辑适用于所有情况。

  1. 验证所有 Type2=1 记录的 ABS(AMT) 是否相同。如果所有 3 条记录都具有相同的 AMT,则该 Num1 为 SET AMTX=ABS(AMT)。或者,如果 Type1 was Y for X12 - 那么我们将改为更新 AmtY = ABS(AMT)

  2. Num1 = Y33 - 在这种情况下,我们再次想要验证 ABS(AMT)Type2=1 相同。如果它们相等,那么因为 Type1=Y,我们将设置 AmtY =75

  3. Num1=Z44 - 在这种情况下再次验证 ABS(AMT) 与 Type2=1 相同。如果它们不相等,则不更新 AmtY,而是设置 AcctBadInd = 1

最终结果

Num1      Acct      Amt         Type1       Type2        AmtX     AmtY    AcctBadInd
  X12       111       90           X          1            90     NULL    NULL
  X12       222       -90          X          1            90     NULL    NULL
  X12       333       90           X          1            90     NULL    NULL

  Y33       111       75           Y          1            NULL     75    NULL
  Y33       444       -75          Y          1            NULL     75    NULL

  Z44       111       55           Y          1            NULL     NULL    1
  Z44       444       -65          Y          1            NULL     NULL    1
  Z44       111       55           Y          0            NULL     NULL    NULL

我正在为此苦苦挣扎,我不期待答案,但至少会得到提示或任何帮助,这样我才能继续前进。更重要的是,如果这能够以我想象的方式实现而无需编写天知道有多少代码。

如果我理解正确的话,你可以这样做:

with cte as (
select * , type2, max(abs(Amt)) minAmt, min(abs(Amt)) maxAmt, count(*) cnt 
from table 
group by Num1 , type2
);

update t1
set   AmtX = case when cnt> 1 and Type2=1 and t1.type1 = 'X' and minAmt = maxAmt then minAmt end
    , AmtY = case when cnt> 1 and Type2=1 and t1.type1 = 'Y' and minAmt = maxAmt then minAmt end
    , AcctBadInd = case when cnt> 1 and Type2=1 and minAmt <> maxAmt then 1 end
from table t1 
join cte on t1.Num1 = cte.Num1
and t1.type2 = cte.type2

使用 window 函数

with t as (
    select *,
    AmtXnew = case when min(ABS(AMT)) over(partition by Num1, Type2) = max(ABS(AMT)) over(partition by Num1, Type2) 
                     and Type2 = 1 and Type1 ='X' then ABS(AMT) 
                else NULL end,
    AmtYnew = case when min(ABS(AMT)) over(partition by Num1, Type2) = max(ABS(AMT)) over(partition by Num1, Type2) 
                     and Type2 = 1 and Type1 ='Y' then ABS(AMT) 
                else NULL end,
    AcctBadIndnew = case when min(ABS(AMT)) over(partition by Num1, Type2) <> max(ABS(AMT)) over(partition by Num1, Type2) 
                     and Type2 = 1 then 1 else NULL end
    from tbl
)
update t set AmtX = AmtXnew,AmtY = AmtYnew, AcctBadInd = AcctBadIndnew;