![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите оптимизировать запрос (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]для начала сделайте цены как в хьюстоне. тогда потерь от скидок не будет.
так как скидок не потребуется