SQL Server 2012:有条件地增加计数器用户ROW_NUMBER()
我想应用ROW_NUMBER()
来根据特定条件增加一个计数器。SQL Server 2012:有条件地增加计数器用户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
列,我试图实现业务逻辑如下:
- 对于每个Id,从1开始,如果DSR小于42,则递增
Prep
计数器。 - 如果它是42或更大,请将Prep计数器重置为1.
的PrepIndicator
,实际上,创建一个标志,以实现这一点,因为如果PrepIndicator = 1
然后Prep = 1
。如果PrepIndicator = 2
,则增加Prep
。
如果可能,我宁愿在没有PrepIndicator
列的情况下实现此目标。
我该如何达到这个条件增量ROW_NUMBER()
?
我已经试过
ROW_NUMBER() OVER (PARTITION BY id, PrepIndicator ORDER BY id)
,但它似乎不工作时DSR
为>= 42
。
任何建议或帮助将是伟大的。谢谢!
首先,您需要显式排序。如果你有一个以前的价值,“增加柜台”只有意义。您可以将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
首先,你需要添加一个主键,因为在一个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
你可以注意到,在这种情况下,任何行都没有位置变化。
您可以检查row_number()calc的over节中使用的条件的代码。它不适合我(全部准备= 1) – 2014-10-01 03:46:01
我提出的代码适用于我。没有看到你自己试过的东西,我不能告诉你它有什么问题;然而,我可以问你是否添加了我在前面的答案中提到的主键。 – SylvainL 2014-10-01 03:49:03
查询需要按照一致的方式进行排序。有没有任何id/date/...列会对此有用? – 2014-09-30 04:25:42