2014-09-30 60 views
4

我想应用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

任何建议或帮助将是伟大的。谢谢!

+0

查询需要按照一致的方式进行排序。有没有任何id/date/...列会对此有用? – 2014-09-30 04:25:42

回答

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 
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 

你可以注意到,在这种情况下,任何行都没有位置变化。

+0

您可以检查row_number()calc的over节中使用的条件的代码。它不适合我(全部准备= 1) – 2014-10-01 03:46:01

+0

我提出的代码适用于我。没有看到你自己试过的东西,我不能告诉你它有什么问题;然而,我可以问你是否添加了我在前面的答案中提到的主键。 – SylvainL 2014-10-01 03:49:03