Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Подкиньте идею, как оптимизировать запрос  [new]
Константин Гулаков
Member

Откуда:
Сообщений: 35
Задачка в том, чтобы посчитать некое значение поля основываясь на предыдущей строке таблицы (стоящей выше текущей). Предыдущей считается строка с меньшим значением поля Ide на 1. ide - primary key. В таблице Т примерно 300 строк.
Запрос этот выполняется порядка 20 секунд. Это очень много. Вот тот перебор, на который уходит 98% времени.


Declare IdCursor Cursor For Select [Ide], Arrival, Expend, Remnant From T
Open IdCursor
Fetch Next From IdCursor into @LastId, @Arrival, @Expend, @LastR
Fetch Next From IdCursor into @LastId, @Arrival, @Expend, @R
While @@Fetch_Status=0
Begin
Set @R=Round(@LastR+@Arrival-@Expend,3)
update T SET
Remnant=@R
where [Ide]=@LastId
Select @LastR=@R
Fetch Next From IdCursor into @LastId, @Arrival, @Expend, @R
End
Close IdCursor
Deallocate IdCursor

Подкиньте идею, как это можно ускорить.
А может такие вещи обязан делать клиент???
28 мар 05, 15:31    [1420078]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
ChA
Member

Откуда: Москва
Сообщений: 11129
SELECT /* Считаем что надо */
FROM T AS t1 -- текущая строка
LEFT JOIN T AS t2 ON (t2.IDE = t1.IDE - 1) -- предыдущая строка
?
28 мар 05, 15:40    [1420138]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
Критик
Member

Откуда: Москва / Калуга
Сообщений: 34245
Блог
>ChA
Это будет работать, если нет удаленных строк, а если есть, то в из cамообъединения получим T2.null.
То бишь для последовательности ключей 1,2,3,10,11,12 запрос не будет работать. Кстати, а что запрос выдаст для первой строки?)

>Константин Гулаков Вы точно уверены, что последовательность ключевого поля неразрывна?
28 мар 05, 15:56    [1420200]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
ChA
Member

Откуда: Москва
Сообщений: 11129
Критик
Это будет работать, если нет удаленных строк
Если внимательно прочитать
Константин Гулаков
Предыдущей считается строка с меньшим значением поля Ide на 1

Во-торых, это была всего лишь идея, не более того, остальное пусть додумывает автор исходного вопроса.
Критик
Кстати, а что запрос выдаст для первой строки?
А как Вы думаете, почему в шаблоне использован LEFT, а не INNER ? Правильно или нет, опять же считать автору вопроса...
28 мар 05, 16:05    [1420244]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
Константин Гулаков
Member

Откуда:
Сообщений: 35
В том, что последовательность primary key неразрывна, я уверен.
Предложеный вариант хорош, но к сожалению не сработал, потому как в формуле для очередного значения поля
Set @R=Round(@LastR+@Arrival-@Expend,3)
присутствует значение этой же формулы полученое в предыдущий раз (@LastR).
Может быть к этому варианту еще один вложеный запрос нужно придумать?...
28 мар 05, 16:14    [1420289]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
ChA
Member

Откуда: Москва
Сообщений: 11129
Константин Гулаков
Хех, цэ другэ дило. Невнимательно посмотрел на Ваш курсор, у Вас нечто типа накапливающейся суммы. Посмотрите в поиске, про это много было.
28 мар 05, 16:19    [1420311]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
ChA
Member

Откуда: Москва
Сообщений: 11129
Константин Гулаков

Для 300 строк в таблице T Ваш курсор считается 20 секунд ? Бред какой-то, Вы что-то не договариваете...
28 мар 05, 16:33    [1420398]     Ответить | Цитировать Сообщить модератору
 Re: Подкиньте идею, как оптимизировать запрос  [new]
ChA
Member

Откуда: Москва
Сообщений: 11129
Попробуйте так
DECLARE @LastR int, @LastId int, @Arrival int, @Expend int, @R int
DECLARE IdCursor CURSOR FOR SELECT [Ide], Arrival, Expend, Remnant FROM T ORDER BY [Ide]
OPEN IdCursor
FETCH NEXT FROM IdCursor INTO @LastId, @Arrival, @Expend, @LastR
FETCH NEXT FROM IdCursor INTO @LastId, @Arrival, @Expend, @R
WHILE @@FETCH_STATUS = 0 Begin
	UPDATE T SET @LastR = Remnant = ROUND(@LastR + @Arrival - @Expend, 3)
	WHERE [Ide] = @LastId
	FETCH NEXT FROM IdCursor INTO @LastId, @Arrival, @Expend, @R
END
CLOSE IdCursor
DEALLOCATE IdCursor
Я вообще не понимаю, что у Вас считалось, Вы фетчили абсолютно произвольно, а не по порядку [Ide].
28 мар 05, 16:44    [1420452]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить