Альтернатива курсора или к вопросу об остатках

AlexanderVS
Дата: 30.01.2001 07:46:46
Я это решил так: Открывается курсор, содержащий все счета по которым было движение до указанной даты, считываем из курсора строку и выбираем из таблицы остатков последнюю запись по данному счету, если отчетная дата и дата проводки совпали, то выбираются текущие остатки и обороты, иначе Исходящий остаток = Входящему, а обороты = 0. Далее полученные переменные вставляются во временную таблицу, при условии что хотя бы одно из значений <>0. После чего считывается следующая запись из курсора и все повторяется.
-----------------------------------
FETCH Schets
INTO @IDL, @IDA, @mType, @DEPO, @Label
WHILE @@Fetch_Status = 0
BEGIN
/*Получить остаток и обороты по лицевому счету на указанную дату*/
select @Dt = (select top 1 Date_ from Rest where ID_LS = @IDL AND Date_ <= @Dat ORDER BY Date_ DESC)
if @Dt = @Dat
/*Если за указанную дату есть проводка*/
SELECT TOP 1 @RestIN = Rest_In, @Deb = Debet, @Cred = Credit, @RestOut = Rest_Out
FROM Rest
WHERE ID_LS = @IDL AND Date_ <= @Dat
ORDER BY Date_ DESC
else
/*Иначе Исходящий остаток = Входящему, а обороты = 0*/
SELECT TOP 1 @RestIN = Rest_Out, @Deb = 0, @Cred =0 , @RestOut = Rest_Out
FROM Rest
WHERE ID_LS = @IDL AND Date_ <= @Dat
ORDER BY Date_ DESC
if @RestIN<>0 or @Deb<>0 or @Cred<>0 or @RestOUT<>0
INSERT INTO tmpOBOROT(IDA, IDL, Depo, Schet, Type, Rest_IN, Debet, Credit, REST_OUT, UserID)
VALUES ( @IDA,@IDL, @DEPO, @Label, @mType,@RestIN, @Deb, @Cred, @RestOUT, @UserID)
FETCH Schets
INTO @IDL, @IDA, @mType, @DEPO, @Label
END
CLOSE Schets
-----------------------------------------
Есть ли решение этой задачи без применения серверного курсора?

Всех благ, Александр.
VadimB
Дата: 30.01.2001 10:02:03
Опиши подробнее исходные и результирующие таблицы (смысл каждого поля)
SergSuper
Дата: 30.01.2001 10:38:48
Курсоры нужно использовать там, где важен порядок записей или же нужно работать "чисто канкретно" с записями, например для значений каждой записи нужно вызвать некую процедуру. Данный случай не подходит под эту категорию.

Я бы делал так:

(Как я понял ID_LS - это ключевое поле счета,@IDA,@IDL, @DEPO, @Label, @mType - некие характеристики счета)

create table #d(ID_LS int, d datetime)
create table #о(ID_LS int, Rest_IN money, Debet money, Credit money, REST_OUT money)
create table #i(ID_LS int, Rest_IN money, Debet money, Credit money, REST_OUT money)

insert #d
select ID_LS, max(Date_) from Rest where Date_<@Dat group by ID_LS
-- получаем даты, где надо искать остатки на предыдущий день

insert #o
select d.ID_LS, Rest_Out,0,0,Rest_Out
from #d d, Rest r
where d.ID_LS=r.ID_LS and d=Date_
-- вставляем остатки за предыдущий день как входящие и как исходящие

insert #o
select d.ID_LS, 0,Debet,Credit,Debet-Credit
from Rest
where Date_=@Dat
-- вставляем обороты и поправку на исходящий остаток. Будем считать, что активные счета имеют положительный остаток, пассивные - отрицательный.

insert #i
select ID_LS, sum(Rest_IN), sum(Debit), sum(Credit), sum(REST_OUT)
from #o
group by ID_LS
-- складываем все поправки в итоговую таблицу

INSERT INTO tmpOBOROT(IDA, IDL, Depo, Schet, Type, Rest_IN, Debet, Credit, REST_OUT, UserID)
select IDA, IDL, Depo, Schet, Type, i.Rest_IN, i.Debet, i.Credit, i.REST_OUT,@UserID
from Schets s, #i i
where s.ID_LS=i.ID_LS

Возможны некоторые ошибки, но я думаю смысл понятен.

Представьте сначала что курсоров нет, а Вам нужно сделать нечто. И попробуйте. Курсоры только вредны для начинающих на SQL.

И еще момент - поле Rest_IN в таблице Rest лишнее, получается избыточная информация, я его не использовал.

С приветом Сергей
sergsuper@mail.ru