2011-03-06 59 views
1

我需要一種有效的方法來傳入參數[StartingNumber]並從[StartingNumber]中進行計數,直到找到一個缺失的數字。最大遞歸已用盡

我用下面的SQL來獲取下一個數字:

 DECLARE @StartOffset int 
     SET @StartOffset = 23 
     ; With Missing as (
      select @StartOffset as N where not exists(
    select * from [QUEUE] where QueueNum = @StartOffset AND ismelutash = 1) 
     ), Sequence as 
    (  select @StartOffset as N from [QUEUE] where QueueNum = @StartOffset 
      union all 
      select b.QueueNum from [QUEUE] b inner join Sequence s 
on b.QueueNum = s.N + 1 and b.ismelutash = 1 
     ) 
     select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence)) 

它已經工作了一段時間,但現在當我運行它,我得到「終止聲明。在語句完成之前,最大遞歸100已經耗盡。

任何人有任何想法?由於

編輯:

我加MAXRECURSION但它只是負載和不返回數據:

DECLARE @StartOffset int 
SET @StartOffset = 50 

DECLARE @isMelutash int 
SET @isMelutash = 0 


; With QueueFilters as (
    select queuenum from queue where ismelutash = 1 
), Missing as (
    select @StartOffset as N where not exists(select * from QueueFilters where queuenum = @StartOffset) 
), Sequence as (
    select @StartOffset as N from QueueFilters where queuenum = @StartOffset 
    union all 
    select b.queuenum from QueueFilters b inner join Sequence s on b.queuenum = s.N + 1 
) 
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence)) 
**OPTION(MAXRECURSION 150)** 

回答

3

你可以在當前的代碼中使用MAXRECURSION選項

然而,不需要逐行遞增(使用Itzik Ben-Gan的方法)。這將檢測哪裏沒有行上排隊ismelutash箱子= 1太,因爲它使用的帳簿表作爲參考序列

;WITH 
    Pass0 as (select 1 as C union all select 1), --2 rows 
    Pass1 as (select 1 as C from Pass0 as A, Pass0 as B),--4 rows 
    Pass2 as (select 1 as C from Pass1 as A, Pass1 as B),--16 rows 
    Pass3 as (select 1 as C from Pass2 as A, Pass2 as B),--256 rows 
    Pass4 as (select 1 as C from Pass3 as A, Pass3 as B),--65536 rows 
    Pass5 as (select 1 as C from Pass4 as A, Pass4 as B),--4,294,967,296 rows 
    Tally as (select row_number() over(order by C) as Number from Pass5) 
select TOP 1 
    Number 
from 
    Tally T 
    LEFT JOIN --corrected, oops. 
    [QUEUE] Q ON T.Number = Q.QueueNum AND Q.ismelutash = 1 
where 
    T.Number >= @StartOffset AND T.Number <= 1000000 
    AND 
    Q.QueueNum IS NULL 
ORDER BY 
    T.Number 

編輯:在端

原始代碼與MAXRECURSION提示This link也較好

 DECLARE @StartOffset int 
     SET @StartOffset = 23 
     ; With Missing as (
      select @StartOffset as N where not exists(
    select * from [QUEUE] where QueueNum = @StartOffset AND ismelutash = 1) 
     ), Sequence as 
    (  select @StartOffset as N from [QUEUE] where QueueNum = @StartOffset 
      union all 
      select b.QueueNum from [QUEUE] b inner join Sequence s 
on b.QueueNum = s.N + 1 and b.ismelutash = 1 
     ) 
     select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence)) 
     OPTION (MAXRECURSION 0) 
+0

非常感謝幫助我,一個問題,我把MAXRECURSION和它的加載無限沒有返回數據。如果遞歸是99,它是即時的,但是101或0,它需要永遠。有任何想法嗎?此外,我沒有在SQL中這麼先進,我將如何實現計數表? – Eitan 2011-03-06 08:47:46

+0

因爲它是遞歸:-)這就是爲什麼你有2個無遞歸的答案... – gbn 2011-03-06 08:49:17

+1

它看起來像你的代碼中有一個錯誤:Tally應該加入Queue左連接,而不是內連接。此外,還有一個語法錯誤:並重復。 – 2011-03-06 19:24:24

2

我相信這是等價的,它不使用遞歸:

SELECT COALESCE(MIN(QueueNum) 
     , (SELECT Max(QueueNum) + 1 
      FROM [Queue] 
      WHERE QueueNum > @StartOffset) 
     , @StartOffset) 
    FROM [QUEUE] 
    WHERE QueueNum >= @StartOffset 
    AND ismelutash != 1 
+0

至少有一種情況失敗:Queue中沒有行> @StartOffset – gbn 2011-03-06 08:04:16

+0

好的,這比我第一次想到的有點棘手,但我認爲實際上只有3種情況:簡單的差距隊列,找不到間隙,以及@StartOffset> Max(QueueNum)。修正後的代碼在所有這些情況下與原始輸出相匹配。 – 2011-03-06 08:27:46

+0

這就是爲什麼我使用外部提示表;-) – gbn 2011-03-06 08:37:34