Я провел некоторое тестирование на всех решениях, представленных здесь в других ответах, моей оригинальной опции "Hairy Recursive CTE" и ради полноты простого подхода на основе курсора.К моему большому удивлению, опция курсора показала лучший результат с явным отрывом во всех моих тестах (1K строк, 10KRows, 50K Rows, 500K Rows)
Вот среднее время для каждого подхода для записей 10K:
Волосатая рекурсивная CTE: 3 минуты 55 секунд
ПРИМЕНЕНИЕ КРЕСТА (Бен Демпси): 21-25 секунд
СУБЪЕКТЫ (Тим Хоури): 19-21 секунда
КУРСОР: 1-2 секунды
Вот мое решение на основе курсора:
Declare @temp TABLE(
DocID INT PRIMARY KEY NOT NULL,
SortOrder INT NOT NULL,
PageCount INT NOT NULL,
BegPg int,
EndPg int
)
Insert into @temp (DocID,SortOrder,PageCount)
SELECT top 50000 docid, ROW_NUMBER() OVER (ORDER BY DOCID),Pages FROM tblDocuments
DECLARE @PC int
SET @PC=1
DECLARE @FetchPageCount int
DECLARE @FetchDocID int
DECLARE myCursor CURSOR FOR
SELECT DocID, PageCount FROM @temp ORDER BY SortOrder
OPEN myCursor
FETCH NEXT FROM myCursor INTO @FetchDocID,@FetchPageCount
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE @temp SET BegPg=@PC, EndPg=@PC+ @FetchPageCount-1
WHERE (Docid=@fetchDocid)
SET @PC = @PC + @FetchPageCount
FETCH NEXT FROM myCursor INTO @FetchDocID,@FetchPageCount
END
CLOSE myCursor
DEALLOCATE myCursor
SELECT * FROM @temp
Кто бы могдогадался?Возможно, курсоры не всегда являются злом.
Слово предупреждения: чтобы не поддаваться искушению заменить обновление на синтаксис "WHERE CURRENT OF myCursor", оно выполнялось намного медленнее, чем при использовании текущей версии с предложением where., хотя все еще быстрее, чем большинство других подходов.