powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / "Скажи Нет курсорам и циклам" SergSuper
7 сообщений из 7, страница 1 из 1
"Скажи Нет курсорам и циклам" SergSuper
    #32004741
Michael Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужно получить сумму (разность, что угодно) поля с суммой (разностью и т.д.) полей предыдущих записей с накоплением. Ну хотя бы так:

set nocount on
declare @i as int
create table t (i1 int, i2 int)
select @i = 0
while @i < 5
begin
select @i = @i + 1
insert t(i1) values (@i)
end
--select * from t
select @i = 0
update t set @i = @i + i1, i2 = @i
select * from t
drop table t
set nocount off

Как для SQL Server 7
гарантированно
получить требуемый порядок обработки строк.
Например, order by t.i desc
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004744
set nocount on
declare @i as int
create table #t (id int identity(1,1), i1 int, i2 int null)
select @i = 0
while @i < 5
begin
select @i = @i + 1
insert #t(i1) values (@i)
end
select @i = 0
update t set i2=(Select SUM(i1) from #t tt where tt.id<=t.id) from #t t
select * from #t
drop table #t
set nocount off

Надеюсь, это то, что нужно было получить.
С уважением,
А.Степанов a_stepanov_2000@mail.ru
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004747
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну нельзя ж так серьёзно всё воспринимать

Иногда с курсором действительно бывает получается быстрее. Это для случаев когда важен именно порядок записей. Но к сожалению очень часто народ использует курсоры, где им не место. Происходит это из-за привычек работать по записям в Фоксе или Аксесе.
Чем мне не нравяться курсоры, так это тем, как они убого реализованы. Вместо того чтобы сделать некую конструкцию типа FOR EACH, приходить самому организовывать цикл, читать в переменные, следить за его окончанием.
Допустим у нас есть курсор
declare c cursor for select i1 from t
Вместо того чтобы написать как-нибудь
for_each c into @i select @i2=@i2+@i

я должен писать:

open c
fetch c into @i
while @Fetch_Status=0
begin
select @i2=@i2+@i
fetch c into @i
end

Жутко смотриться если имеются вложенные циклы.

Что касается Вашего вопроса. Если Вы пытаетесь доказать что в отдельных случаях без курсоров не обойтись - я переубеждать не буду, оставайтесь при своём мнении, к тому же я уже написал, что есть ситуации когда использование курсора предпочтительней. Но иногда лучше представить что нет курсоров и пытать как-то выкручиваться. В результате иногда удается найти более красивое решение.

Что касается Вашей задачи. Вот так в лоб она не решается. Я обычно делал примерно так:
set nocount on
declare @i as int
create table #t (i1 int, i2 int)
select @i = 0
while @i < 5
begin
select @i = @i + 1
insert #t(i1) values (@i)
end

select t1.i1, sum(t2.i1) i2
into #t0
from #t t1, #t t2
where t2.i1<=t1.i1
group by t1.i1

update #t
set i2=t0.i2
from #t t1, #t0 t0
where t1.i1=t0.i1

select * from #t

drop table #t
drop table #t0
set nocount off

Работать оно будет скорее всего медленнее чем с курсором, хотя если использовать паременные-таблицы - то не факт.

Замечу еще что в SQL 4.0 и 6.0 синтаксис допускал конструкции без использования промежуточной таблицы.

С приветом Сергей
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004751
Michael Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 SergSuper
Ну что Вы, доказать я ничего не хочу. Как раз наоборот, пытаюсь уйти от встроенного курсора.

2Александр Степанов
У меня нет уверенности, что identity(кстати и primary key, и clustered) гарантирует требуемый порядок обработки строк

2 All
Увы, агрегатные функции не подходят, пользовательских в 7 нет.
А логика такая (where t2.i1<=t1.i1 как то не пришить):

create procedure dbo.MidPrice
@old_quantity as float,
@old_price as float,
@new_quantity as float,
@new_price as float,
@sum_quantity as float output,
@mid_price as float output
as
select @sum_quantity = @old_quantity + @new_quantity

if @sum_quantity = 0
begin
select @mid_price = 0
end
else -- @sum_quantity <> 0
begin
if @sum_quantity * @old_quantity < 0
begin
select @mid_price = @new_price
end
else -- @sum_quantity * @old_quantity > 0
begin
select @mid_price = abs((@old_price * @old_quantity + @new_price * @new_quantity) / @sum_quantity)
end
end
go --end procedure dbo.MidPrice
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004756
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вообще если это SQL2000, то можно написать функцию. Будет выглядеть очень неплохо.

Это случайно не расчет средней цены ценных бумаг?

Кстати, а зачем писать каждый раз begin/end? Так же вроде наглядней:
if @sum_quantity = 0
select @mid_price = 0
else -- @sum_quantity <> 0
if @sum_quantity * @old_quantity < 0 select @mid_price = @new_price
else -- @sum_quantity * @old_quantity > 0 select @mid_price = abs((@old_price * @old_quantity + @new_price * @new_quantity) / @sum_quantity)
или
select @mid_price = case
when @sum_quantity = 0 then 0
when @sum_quantity * @old_quantity < 0 then @new_price
else abs((@old_price * @old_quantity + @new_price * @new_quantity) / @sum_quantity) end
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004758
Michael Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Ну вообще если это SQL2000, то можно написать функцию. Будет выглядеть очень неплохо.

7.0

>Это случайно не расчет средней цены ценных бумаг?

Да

>Кстати, а зачем писать каждый раз begin/end? Так же вроде наглядней:

Привычка, так же как совать везде as и into


Кстати, что думаете про топик "Встроенный курсор"
...
Рейтинг: 0 / 0
"Скажи Нет курсорам и циклам" SergSuper
    #32004759
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
про топик "Встроенный курсор"

Ой тоскливо мне смотреть туда было. Это ж думать уже надо...
Вобщем ничего не скажу, я сам курсоры раза 2-3 всего использовал. Я как увижу while @@fetch_status = 0 - плохо становиться
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / "Скажи Нет курсорам и циклам" SergSuper
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]