簡體   English   中英

SQL Server 2012:有條件地增加計數器用戶ROW_NUMBER()

[英]SQL Server 2012: Conditionally Incrementing a counter user ROW_NUMBER()

我正在嘗試應用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忽略PrepIndicator列,我試圖實現的業務邏輯如下:

  • 對於每個Id,從1開始,如果DSR小於42,則遞增Prep計數器。
  • 如果為42或更高,請將Prep計數器重置為1。

實際上, PrepIndicator會創建一個標志來實現它,如果PrepIndicator = 1Prep = 1 如果PrepIndicator = 2 ,則增加Prep

如果可能的話,我更願意在沒有PrepIndicator專欄的情況下實現這一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的行現在位於第二個位置。 這顯然是你不想擁有的。 在Select count(*)...的情況下,我們在分組完成后的最后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

您可以注意到,在這種情況下,任何行的位置都沒有變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM