Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Помогите оптимизировать запрос (D2007, BDE, Paradox) [Paradox]


petvv ©   (2008-11-28 09:25:00) 

В общем есть такой код:

procedure TMainForm.GetCena;
begin
 Cena.Active:=False;
 Cena.SQL.Clear;
 Cena.SQL.Add('select price from Statist where Statist.DateTime<:QDBeg and Statist.Product='+IntToStr(Temp.FieldByName('Product').Value) +' and Statist.Osnovanye=0');
 Cena.ParamByName('QDBeg').AsDateTime:=Temp.FieldByName('DateTime').Value;
 Cena.Active:=True;
 Cena.RecordCount;
 Cena.FindLast;
 Cena1:=Cena.FieldByName('Price').Value;
 Cena.Close;
end;

procedure TMainForm.btnStartClick(Sender: TObject);
begin
DT;
 if DEnd<DBeg then
   begin
     MessageBox(0,'Дата окончания периода меньше даты начала периода !','Неверныё период расчётов',0);
     Exit;
 end;
qOsn.Close;
qOsn.Params[0].AsDateTime:=DBeg;
qOsn.Params[1].AsDateTime:=DEnd;
qOsn.Active:=True;
//********************************
Temp.Active:=False;
Temp.DataBaseName:='STATION32';
Temp.TableName:='Temp';
Temp.TableType:=ttParadox;
Temp.FieldDefs.Clear;
Temp.FieldDefs.Add('DateTime',ftDateTime);
Temp.FieldDefs.Add('Marka',ftString,50,False);
Temp.FieldDefs.Add('Product',ftFloat,0,False);
Temp.FieldDefs.Add('Osnovan',ftString,50,False);
Temp.FieldDefs.Add('Osnovanye',ftFloat,0,False);
Temp.FieldDefs.Add('Litr',ftFloat,0,False);
Temp.FieldDefs.Add('Summa',ftFloat,0,False);
Temp.FieldDefs.Add('Price',ftFloat,0,False);
Temp.FieldDefs.Add('Delta',ftFloat,0,False);
Temp.FieldDefs.Add('Report',ftBoolean,0,False);
Temp.FieldDefs.Add('Discount',ftBoolean,0,False);
Temp.CreateTable;
Temp.Active:=True;
Temp.Edit;
Temp.First;
for n:=1 to qOsn.RecordCount do begin
 Temp.Append;
 Temp.FieldByName('Product').AsString:=qOsn.FieldByName('Product').Value;
 Temp.FieldByName('Osnovanye').AsString:=qOsn.FieldByName('Osnovanye').Value;
 Temp.FieldByName('Discount').AsString:=qOsn.FieldByName('Discount').Value;
 Temp.FieldByName('DateTime').AsDateTime:=qOsn.FieldByName('DateTime').Value;
if qOsn.FieldByName('Discount').Value=True then GetCena
else Cena1:=qOsn.FieldByName('Price').Value;

 Temp.FieldByName('Marka').AsString:=qOsn.FieldByName('Marka').Value;
 Temp.FieldByName('Osnovan').AsString:=qOsn.FieldByName('Name').Value;
 Temp.FieldByName('Litr').AsFloat:=qOsn.FieldByName('LitFact').Value;
 if qOsn.FieldByName('Report').Value=True then Temp.FieldByName('Summa').AsFloat:=qOsn.FieldByName('CurFact').Value
 else if qOsn.FieldByName('Report').Value=False then Temp.FieldByName('Summa').AsFloat:=0;

 Temp.FieldByName('Price').AsFloat:=qOsn.FieldByName('Price').Value;
 s:=(qOsn.FieldByName('LitFact').Value*Cena1)-qOsn.FieldByName('CurFact').Value;
 if s<0.4 then s:=0;
 Temp.FieldByName('Delta').AsVariant:=s;
 Temp.FieldByName('Report').AsBoolean:=qOsn.FieldByName('Report').Value;

 qOsn.Next;
end;


Так вот, при вызове вот этого:

if qOsn.FieldByName('Discount').Value=True then GetCena

Отчёт формируется минуты 2, а если опустить то мнгновенно.

Для чего это нужно объясняю: формируется отчёт по потерям на скидках, скидка это

s:=(qOsn.FieldByName('LitFact').Value*Cena1)-qOsn.FieldByName('CurFact').Value;

Цену, по которой был продан ГСМ со скидкой выдернуть из таблицы нет возможности, т.к. там указана только текущая цена, а цены меняются постоянно.

В самой таблице откуда дёргаются данные и переносятся в промежуточную таблицу

Temp.FieldByName('Price').AsFloat:=qOsn.FieldByName('Price').Value;

Так вот, чтобы получить розничную цену на момент продажи необходимо взять предыдущую, первую попавшую розничную цену. Но благодаря этому отчёт формируется минуты 2, а это не есть гут.

Подскажите, как построить основной запрос, чтобы в нём дёргалась предыдущая, розничная цена, без всяких там моих извращений


Loginov Dmitry   (2008-12-01 22:15:00) [1]

> Цену, по которой был продан ГСМ со скидкой выдернуть из
> таблицы нет возможности, т.к. там указана только текущая
> цена, а цены меняются постоянно.


если "текущая цена" это НЕ тоже самое, что и "цена, по которой был продан ГСМ со скидкой", что тогда есть "текущая цена"?

Вообще-то исходных данных маловато. Мы видим, что есть некая таблица "Statist", в которую входят как минимум 3 поля: price, DateTime, Product, Osnovanye.
Также существует некая таблица, с которой осуществляется работа через набор данных "qOsn", включающая поля:
Product, Osnovanye, Discount, DateTime, Price, Marka, Name, LitFact, CurFact, Report. Это одна и таже таблица, или разные? Судя по наименованиям Statist и qOsn - наверно разные. Тогда какое назначение у таблицы qOsn и у таблицы Statist? И почему "Цену, по которой был продан ГСМ со скидкой выдернуть из таблицы нет возможности", с чем связаны данные особенности проектирования БД?


petvv   (2008-11-30 20:38:00) [2]


> Наверное надо брать цену на максимальную дату меньше заданой,
>  а не "первую попавшую"?


Я имел в виду тоже самое, только выразил свою мыслю криво.


petvv   (2008-11-30 20:28:00) [3]


> вариант2подумать и попробовать добавить этот запрос (передланный
> конечно) к основному, для исключения временной таблицы вообще
> как класса.


Вот этот вариант подходит больше. Завтра на работе попробую навоять запрос. А промежуточную таблицу использовал потому, что пришли с вопросом сегодня, а сделать надо было вчера вот и пришлось использовать таблицу, чтобы сделать вчера.


Sergey13   (2008-11-28 11:53:00) [4]

как вариант1
перед расчетом выполнить запрос

select s1.Product,s1.price
from Statist s1
where Statist.Osnovanye=0' and Statist.DateTime=
(select max(DateTime) from Statist s2 where s1.Product=s2.Product s2.DateTime<:QDBeg)


и в GetCena искать по нему locate по produkt.
Желателен индекс по Product+DateTime

вариант2
подумать и попробовать добавить этот запрос (передланный конечно) к основному, для исключения временной таблицы вообще как класса.


Sergey13   (2008-11-28 11:36:00) [5]

> [0] petvv   (28.11.08 09:25)
> Так вот, чтобы получить розничную цену на момент продажи
> необходимо взять предыдущую, первую попавшую розничную цену.

Наверное надо брать цену на максимальную дату меньше заданой, а не "первую попавшую"?


Slym   (2008-11-28 11:22:00) [6]

petvv   (28.11.08 9:25)
Cena.FindLast;
Cena1:=Cena.FieldByName('Price').Value;

ты уверен что FindLast это последняя цена? я нет! потому что не ORDER BY DateTime

я бы сделал так

//эту операцию выполнить 1 раз перед началом работы
Cena.SQL.Add('select price from Statist where (Osnovanye=0) and (DateTime<:QDBeg) and (Product=:ProdID) ORDER BY DateTime DESC');
Cena.Prepare;

function TMainForm.GetCena(const Date:TDateTime;ProdID:integer;):variant;
begin
Cena.ParamByName('QDBeg').AsDateTime:=Date;
Cena.ParamByName('ProdID').Value:=ProdID;
Query1.Refresh;//непомню сработает или нет...
if not Cena.isEmpty then
 result:=Cena.Fields[0].Value
else
 result:=0;
end;


Sergey13   (2008-11-28 10:37:00) [7]

> [3] Поросенок Винни-Пух ©   (28.11.08 10:25)
> для парадокса это сильно повлияет на производительность?

никак не повлияет, мне просто интересно.


Поросенок Винни-Пух   (2008-11-28 10:25:00) [8]

И почему частично ты используешь параметры, а частично подстановку?

для парадокса это сильно повлияет на производительность?
оно что его, запрепарит если параметры будут?


Sergey13   (2008-11-28 10:16:00) [9]

> [0] petvv   (28.11.08 09:25)

> Так вот, при вызове вот этого:
>
> if qOsn.FieldByName('Discount').Value=True then GetCena
>
> Отчёт формируется минуты 2, а если опустить то мнгновенно.

Значит запрос в GetCena работает медленно. Какие есть индексы на Statist?
И почему частично ты используешь параметры, а частично подстановку?


Поросенок Винни-Пух   (2008-11-28 10:00:00) [10]

для начала сделайте цены как в хьюстоне. тогда потерь от скидок не будет.
так как скидок не потребуется


Наверх

Титульная страница Поиск, карта сайта Написать письмо