我遇到一种情况,我必须根据同一记录组的上一行中同一列上的值,将增量值更新为一列。
“ COUNT”列的更新规则为:
For the very 1st row of a particular REFNO,
If Amount 1 = Amount 2 then
COUNT = 1
Else
COUNT = 0
对于特定REFNO的所有其他行(第一行除外):
If Amount 1 = Amount 2 then
COUNT = COUNT from previous row for the same REFNO + 1
Else
COUNT = COUNT from previous row for the same REFNO
因此结果应如下所示:
尽管我显示的样本数据只有14条记录,但我要更新的实际表中将有几百万行。因此,我正在寻找一种解决方案,该解决方案将执行基于集合的更新,而不是逐行处理!!
答案 0 :(得分:2)
您可以从使用window functions计算数字的CTE中进行更新。
下面的SQL首先计算相等数量的row_number。
然后,对于其他数量不相等的其他对象,采用前一个row_number的最大值。
WITH CTE AS
(
SELECT *,
(CASE
WHEN [Amount 1] = [Amount 2]
THEN rn
ELSE MAX(rn) OVER (PARTITION BY [REFNO] ORDER BY [ROW ID] ASC ROWS UNBOUNDED PRECEDING)
END) as rnk
FROM (
SELECT
[ROW ID], [REFNO], [Amount 1], [Amount 2], [COUNT],
(CASE
WHEN [Amount 1] = [Amount 2]
THEN ROW_NUMBER() OVER (PARTITION BY [REFNO], IIF([Amount 1] = [Amount 2],0,1) ORDER BY [ROW ID] ASC)
ELSE 0
END) AS rn
FROM PAYMENT
) q
)
UPDATE CTE
SET [COUNT] = rnk;
对 db <>小提琴here
的测试答案 1 :(得分:0)
尝试
declare @t table (
rowid int identity,
refno int,
amount1 int,
amount2 int
)
insert into @t(refno,amount1,amount2) values (1000000,100,200)
insert into @t(refno,amount1,amount2) values (1000000,250,250)
insert into @t(refno,amount1,amount2) values (1000000,300,300)
insert into @t(refno,amount1,amount2) values (1000000,400,400)
insert into @t(refno,amount1,amount2) values (1000010,400,100)
insert into @t(refno,amount1,amount2) values (1000010,200,100)
insert into @t(refno,amount1,amount2) values (1000010,100,300)
insert into @t(refno,amount1,amount2) values (1000021,400,400)
insert into @t(refno,amount1,amount2) values (1000021,200,100)
insert into @t(refno,amount1,amount2) values (1000032,200,200)
insert into @t(refno,amount1,amount2) values (1000032,300,300)
insert into @t(refno,amount1,amount2) values (1000033,200,100)
insert into @t(refno,amount1,amount2) values (1000033,200,100)
select rowid,refno,amount1,amount2,rw-1 as count
from (
select
row_number() over(partition by amount1,amount2 order by rowid) rw,*
from @t) as src
答案 2 :(得分:0)
此代码适用于该特定集合,但不能保证在某些情况下它不起作用:
CREATE TABLE #tmp(
RowID INT IDENTITY(1,1),
RefNo INT,
Amount1 INT,
Amount2 INT
)
INSERT INTO #tmp(RefNo,Amount1,Amount2)
SELECT * FROM (VALUES
(100000,100,200),
(100000,250,250),
(100000,300,300),
(100000,400,400),
(100000,400,100),
(100010,200,100),
(100010,100,300),
(100010,400,400),
(100021,200,100),
(100021,200,200),
(100032,300,300),
(100032,200,100),
(100033,200,100),
(100033,200,100)) AS x(a,b,c)
;WITH Try1 AS (SELECT t1.*, [Count] =
CASE WHEN t1.Amount1 != t1.Amount2 AND
(t2.RowId IS NULL OR t2.Amount1 != t2.Amount2) THEN 0
WHEN t1.Amount1 != t1.Amount2 AND t2.Amount1 = t2.Amount2 THEN t2.RowId
WHEN t1.Amount1 = t1.Amount2 AND t2.RowId IS NULL THEN t1.RowId
WHEN t1.Amount1 = t1.Amount2 AND t2.RowId IS NOT NULL THEN t1.RowId
END
, NextRefNo = CASE WHEN t2.RowId IS NULL THEN 1 ELSE 0 END
FROM #tmp AS t1
OUTER APPLY ( SELECT * FROM #tmp AS t2
WHERE t2.RowId = t1.RowID - 1 AND t2.RefNo = t1.RefNo) AS t2)
, Try2 AS (SELECT RowID, RefNo, Amount1, Amount2, [Count]
, NextRefNo = ISNULL(t2.NextRefNo,0)
FROM Try1 AS t1
OUTER APPLY ( SELECT NextRefNo FROM Try1 AS t2
WHERE t2.[Count] > 0 AND t2.NextRefNo = 1
AND t2.RefNo = t1.RefNo ) AS t2)
SELECT RowID, RefNo, Amount1, Amount2
, [Count] = DENSE_RANK() OVER(PARTITION BY RefNo ORDER BY [Count]) - 1 + NextRefNo
FROM Try2
ORDER BY RowID;