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,并且相同的逻辑适用于所有情况。
验证所有 Type2=1
记录的 ABS(AMT)
是否相同。如果所有 3 条记录都具有相同的 AMT,则该 Num1 为 SET AMTX=ABS(AMT)
。或者,如果 Type1 was Y for X12
- 那么我们将改为更新 AmtY = ABS(AMT)
Num1 = Y33
- 在这种情况下,我们再次想要验证 ABS(AMT)
与 Type2=1
相同。如果它们相等,那么因为 Type1=Y
,我们将设置 AmtY =75
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;
我手头有一项有趣的任务,我正在想办法去做。
假设我在 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,并且相同的逻辑适用于所有情况。
验证所有
Type2=1
记录的ABS(AMT)
是否相同。如果所有 3 条记录都具有相同的 AMT,则该 Num1 为SET AMTX=ABS(AMT)
。或者,如果Type1 was Y for X12
- 那么我们将改为更新AmtY = ABS(AMT)
Num1 = Y33
- 在这种情况下,我们再次想要验证ABS(AMT)
与Type2=1
相同。如果它们相等,那么因为Type1=Y
,我们将设置AmtY =75
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;