我正在尝试应用ROW_NUMBER()
根据特定条件递增计数器。
我的数据如下所示,目标计数器为Prep
列
id DSR PrepIndicator Prep
--------------------------------------
1662835 -1 1 1
1662835 14 2 2
1662835 14 2 3
1662835 20 2 4
1667321 -1 1 1
1667321 30 2 2
1667321 14 2 3
1680648 -1 1 1
1680648 14 2 2
1680648 60 1 1
1680648 14 2 2
1680648 14 2 3
1683870 -1 1 1
1683870 12 2 2
1683870 10 2 3
1683870 60 1 1
1683870 7 2 2
暂时忽略PrepIndicator
列,我尝试实现的业务逻辑如下:
Prep
计数器。 PrepIndicator
实际上会创建一个标记来实现此功能,如果PrepIndicator = 1
则为Prep = 1
。如果PrepIndicator = 2
,则增加Prep
。
如果可能,我希望在没有PrepIndicator
列的情况下实现此目的。
如何使用ROW_NUMBER()
实现此条件增量?
我试过
ROW_NUMBER() OVER (PARTITION BY id, PrepIndicator ORDER BY id)
但DSR
为>= 42
时似乎无效。
任何建议或帮助都会很棒。谢谢!
答案 0 :(得分:0)
首先,您需要明确的订购。 "递增计数器"只有你有一个以前的值才有意义。您可以向表中添加IDENTITY列,也可以使用ROW_NUMBER() OVER ORDER BY(/* your logic here */)
。在你的表中,你甚至没有前三列的唯一值(见1680648,14,2),所以我认为添加一个ID是可行的。
要做你想要达到的目标,我相信你必须在循环中做到这一点。如果您使用ROW_NUMBER()
,您可能希望选择临时表。根据您的问题的性质,术语计数器表示您将拥有一个变量。
UPDATE TableA SET rowId = ROW_NUMBER() OVER(ORDER BY id, DSR, PrepIndicator)
然后"有条件的"似乎很好地利用了CASE
DECLARE @counter INT = 1
DECLARE @row INT = 1
DECLARE @DSR INT
UPDATE TableA SET Prep = @counter
SET @row = (SELECT rowId FROM TableA WHERE rowId > @row)
WHILE EXISTS( SELECT TOP 1 1 FROM TableA WHERE rowId = @row )
BEGIN
SELECT @DSR = DSR FROM TableA WHERE rowId = @row
SET @counter = CASE WHEN @DSR < 42 THEN @counter + 1 ELSE 1 END
UPDATE TableA SET Prep = @counter WHERE rowId = @row
SET @row = (SELECT rowId FROM TableA WHERE rowId > @row)
END
答案 1 :(得分:0)
首先,您需要添加主键,因为SQL表中没有物理顺序;我们可以称之为IdK。然后,以下代码应该为您提供所需内容:
select *, row_number() over (partition by Id, (Select Count (*) from MyTable t2 where t2.idk <= t1.idk and t2.id = t1.id and DSR >= 42) order by idk) prep
from MyTable t1
order by idk
至于为什么你的代码不起作用,这是因为在分区/编号完成之前首先对行进行分组。在分区的两列id和PrepIndicator的情况下,我们在编号之前的最后5行获得以下中间结果:
id DSR PrepIndicator Row_Number (Id, PrepIndicator)
1683870 -1 1 1
1683870 60 1 2
1683870 12 2 1
1683870 10 2 2
1683870 7 2 3
请注意,DSR = 60的行现在位于第二个位置。这显然是你不想拥有的。在选择计数(*)...的情况下,我们在分组完成后的最后5行中得到以下结果,就在编号之前:
id DSR ...Count() Row_Number (Id, ...Count())
1683870 -1 0 1
1683870 12 0 2
1683870 10 0 3
1683870 60 1 1
1683870 7 1 2
您可以注意到,在这种情况下,任何行的位置都没有变化。