Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-1110365973
Gerakl
2005-03-09 13:59
2005.03.20
Delphi2005 + DotNet


6-1105614715
MInd_f
2005-01-13 14:11
2005.03.20
Как юзать IdPOP3 через проксю?


1-1109693041
Vasilisk
2005-03-01 19:04
2005.03.20
Быстрый поиск по HTML


3-1108704613
h1der
2005-02-18 08:30
2005.03.20
Delphi изменяет заголовок таблицы FoxPro


14-1109663563
Nikolay M.
2005-03-01 10:52
2005.03.20
Поисковик от разработчиков Рамблера для разработчиков





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский