Форум: "Базы";
Текущий архив: 2005.03.20;
Скачать: [xml.tar.bz2];
ВнизКак в хранимой процедуре посчитать среднехронологические значения Найти похожие ветки
← →
AlexandrKu (2005-02-18 11:01) [0]Есть
база типа
account, date_carry, rest
400000,"12.02.2005",135
400001,"25.10.2004",3000
400001,"28.10.2004",1800
400001,"29.10.2004",7800
Необходимо посчитать по счету 400001 таким образом:
1. виртуально обавить недастоющие дни (25,26)
400001,"25.10.2004",3000
400001,"26.10.2004",3000
400001,"27.10.2004",3000
400001,"28.10.2004",1800
400001,"29.10.2004",7800
2. посчитать сумму остатков и разделить на количество дней (5)
пока дошел вот до чего
CREATE PROCEDURE Dbo.RestA
@account varchar(20) ,
@Datebeg Datetime,
@dateend datetime,
@rest int output
AS
declare
@days integer;
set @days=0;
While @datebeg<=@dateend
begin
select top 1 @rest=@rest+rest
from restdate
where (account=@account) and (Date_carry<=@datebeg)
order by date_carry desc;
set @Datebeg=@Datebeg+1;
set @days=@days+1;
end;
set @rest=@rest/@days;
return @rest;
GO
процедура выдает 0
← →
Ega23 © (2005-02-18 11:12) [1]1. Declare @DatIn datetime, @datOut datetime, @SumRest int, @Result float
2. Set @DatIn="25.10.2004" Set @DatOut="29.10.2004"
3. Select @sumRest=Sum(rest) from restdate where date_Carry between(@DatIn, @DatOut)
5. Select @Result=@SumRest/((Cast(@DatOut) as int) - (Cast(@DarIn) as int))
6. Вроде, всё.
← →
AlexandrKu (2005-02-18 11:54) [2]в данном случае насколько я понимаю он посчитает сумму за 3 дня а нужно за 5
← →
MOA © (2005-02-18 12:03) [3]Попробуйте - вместо
return @rest
вот так:
SELECT @rest AS F_rest
и результат - в датасете.
Так - не ноль?
PS. Я бы написал (не вдаваясь (не меняя) алгоритм, поскольку не совсем ясна задача, например почему res - целое)
set @days=DATEDIFF(day, @datebeg, @dateend);
While @datebeg<=@dateend
begin
SELECT @rest=@rest+rest
from restdate
where (account=@account) and (Date_carry=@datebeg)
set @Datebeg=@Datebeg+1;
end;
Удачи!
← →
MOA © (2005-02-18 12:05) [4]А, понял! Вы так вставляете пропущенные остатки. Моё предыдущее исправление неворно. Сейчас подумаю тщательнее ;)..
← →
AlexandrKu (2005-02-18 12:23) [5]реально я их невставляю я получаю значение остатка в этот день (если записи нет то берется предидущий остаток)
← →
MOA © (2005-02-18 12:35) [6]Придумал без цикла (не проверял!):
set @days=DATEDIFF(day, @datebeg, @dateend)
SELECT
SUM(ALL
CASE DATEDIFF(day, r1.Date_carry, r2.Date_carry)
WHEN 1 THEN r1.rest
ELSE r1.rest * DATEDIFF(day, r1.Date_carry, r2.Date_carry)
END)
FROM restdate r1 LEFT OUTER JOIN restdate r2
ON (r2.Date_carry = (SELECT MIN(r3.Date_carry) FROM restdate r3 WHERE r3.Date_carry > r1.Date_carry))
WHERE (r1.Date_carry >= (SELECT MIN(r4.Date_carry) FROM restdate r4 WHERE r4.Date_carry <= @Datebeg))
AND (r1.Date_carry <= @dateend)
set @rest=@rest/@days
CASE не обязателен ;). Нужно, впрочем, попробовать, что быстрее - всегда умножать даже и на 1, или проверять как тут ;).
Ещё вариант - сформировать таблицу дней и делать запрос с OUTER JOIN - если подобных вычислений много, может оказаться разумным ;).
Удачи!
← →
MOA © (2005-02-18 12:36) [7]Да, и по поводу 0 -то ;) - с датасетом не проходит?.
Дело в том, что в BDE (вроде) припоминается мне глюк - результат процедуры всегда 0 :(.
← →
Ega23 © (2005-02-18 12:42) [8]Дело в том, что в BDE (вроде) припоминается мне глюк - результат процедуры всегда 0 :(.
При чём тут BDE?
← →
MOA © (2005-02-18 12:42) [9]Чёрт. В приведённом моём скрипте пропущены везде связи по account. Вот:
SELECT
SUM(ALL
CASE DATEDIFF(day, r1.Date_carry, r2.Date_carry)
WHEN 1 THEN r1.rest
ELSE r1.rest * DATEDIFF(day, r1.Date_carry, r2.Date_carry)
END)
FROM restdate r1 LEFT OUTER JOIN restdate r2
ON (r2.account=@account)
AND (r2.Date_carry = (SELECT MIN(r3.Date_carry) FROM restdate r3 WHERE (r3.Date_carry > r1.Date_carry) AND (r3.account=@account)))
WHERE (r1.Date_carry >= (SELECT MIN(r4.Date_carry) FROM restdate r4 WHERE (r4.Date_carry <= @Datebeg) AND (r4.account=@account)))
AND (r1.Date_carry <= @dateend) AND (r1.account=@account)
Приношу свои извинения :(.
← →
MOA © (2005-02-18 12:47) [10]>При чём тут BDE?
Ну, на первый взгляд - процедура автора рабочая. Я попробовал нечто похожее - работает. Разве что поставить вместо rest ISNULL(rest,0).
Кстати, сам тоже забыл эту штуку :(.
Однако, вопрос автору: 0 выдаётся в QA? Или в приложении?
← →
MOA © (2005-02-18 12:50) [11]Описка.
MIN(r4.Date_carry) => MAX(r4.Date_carry)
← →
Ega23 © (2005-02-18 12:51) [12]Делай так:
Declare @X int
Set NoCount ON
exec @X=S_MyProc ...
Set NoCount OFF
Select X=@X
← →
AlexandrKu (2005-02-18 12:55) [13]2 MOA QA выдавало NULL и в приложении 0
Нашел ошибку всем спасибо
просто переменную @rest непроинициализировал и он нехотел прибавлять туда результат
перед циклом добавил set @rest=0 и все пошло
еще раз спасибо MOA за то что открыл глаза на тип @rest действительно нужен float
← →
Ega23 © (2005-02-18 13:03) [14]return у тебя ТОЛЬКО int вернуть может.
Делай выводы...
← →
AlexandrKu (2005-02-18 13:15) [15]Т.е. заголовок процедуры:
CREATE PROCEDURE Dbo.RestA
@account varchar(20) ,
@Datebeg Datetime,
@dateend datetime,
@rest float output???
Return @rest -убрать,
таким образом я же верну значение?
← →
Ega23 © (2005-02-18 13:54) [16]Да, вернёшь. Но всё зависит от того, КУДА ты этот результат хочешь получить.
Если на клиент - то проще перед Return поставить Select Rest=@Rest
На клиенте:
Query.SQL.Text:="exec S_MyProc ....";
Query.Open;
Result:=Query.FieldByName("Rest").asFloat;
Если ты эту процедуру из другой ХП хочешь использовать, то тогда лучше через output.
Вариантов много...
← →
Ega23 © (2005-02-18 13:56) [17]Слушай, я от сетки сейчас отключусь, если есть вопросы - пиши на egorov@dedal.dubna.ru, ОК?
← →
AlexandrKu (2005-02-18 14:01) [18]Вообщем в QA все выполняется а в дельфях неберет точнее возвращает 0
ADOStoredProc1.Parameters.ParamByName("@account").value:="70209810700012941602";
ADOStoredProc1.Parameters.ParamByName("@datebeg").value:=DateTimePicker1.DateTime;
ADOStoredProc1.Parameters.ParamByName("@dateend").value:=DateTimePicker2.DateTime;
ADOStoredProc1.ExecProc;
s:=ADOStoredProc1.Parameters.ParamByName("@rest").Value;
Всегда работало (точнее раньше) а сейчас что-то неполучается :(
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2005.03.20;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.038 c