Деякі хитрості. , FoxPro, Бази даних, статті

Покладемо, що для одного ключа з довідника має бути знайдено кілька
різних полів. Не хочеться перевантажувати роботу пошуку вдруге. Якщо потрібна
запис у довіднику знайдена – для іншого поля ні до чого заново робити пошук.

Друге.

SQL select володіє одним неприємним властивість: довжина результуючого поля
оцінюється під час ініціалізації. Тому, якщо для першого запису довідка
відсутня, а для наступної довідка є, то і для порожньої записи потрібно повернути
поле потрібної довжини. Інакше записи з довідника будуть урізані по одній букві.

Ось приклад такої функції

Lparameters pr_id,mydat
Local retcr

If order(“val_course”)!=”datcur”
Set order to datcur in val_course
Endif
retcr=0
If empty(mydat)
set exact off
If seek(str(pr_id,3),”val_course”)
retcr=course
Endif
Else
If set(“NEAR”)=”OFF”
Set near on
Endif
=seek(str(pr_id,3)+dtos(mydat),”val_course”)
If pr_id=val_course.valuta_id
retcr=val_course.course
Endif
Set near off
Endif
Return retcr:

Function getref
Lparameters fld,pr_id,tb,tg

Local fl,tpt,rt,rtt,lnn, fl,fll

fl=tb+”.”+alltrim(fld)
fll=tb+”.”+tg
*** Якщо збігся ключ, можна не шукати, інакше – шукаємо
If not empty(pr_id) and ;
(eval(fll)=pr_id or seek(pr_id,tb,tg))
rtt=eval(fl)
Return rtt
Else
rt=eval(fl)
tpt=type(“rt”)
Do case
Case tpt=”N”
rtt=0
Case tpt=”C”
Lnn=len(eval(fl))
rtt=pad(“”,lnn)
Case tpt=”D”
rtt=ctod(“..”)
Case tpt=”L”
rtt=.f.
Endcase
Return rtt
Endif

Lparameters pr_id,mydat

Local retcr

If order(“val_course”)!=”datcur”
Set order to datcur in val_course
Endif
retcr=0
If empty(mydat)
set exact off
If seek(str(pr_id,3),”val_course”)
retcr=course
Endif
Else
If set(“NEAR”)=”OFF”
Set near on
Endif
=seek(str(pr_id,3)+dtos(mydat),”val_course”)
If pr_id=val_course.valuta_id
retcr=val_course.course
Endif
Set near off
Endif
Return retcr


Приклад використання. Нехай у нас був запит SQL такого вигляду:

Select doc.num,val from doc LEFT OUTER JOIN valuta;
ON doc.valuta_id= Valuta.valuta_id

Тепер пишемо

Select doc.num getref ("val", "doc.valuta_id", "valuta", "valuta_id) as val from doc

Тут звичайно вийшло більш громіздко, ніж у вихідному прикладі, зате можна
додавати ще купу полів з довідників і купу довідників і не бояться при
цьому використовувати пропозицію where в цьому ж sql

Другий приклад складніше.

Є таблиця валют і таблиця курсів валют з ключами валюти, датою і курсом.
Причому в таблицю курсів валют курси можуть записуватися не в порядку часу, а
довільно. Деякі валюти в таблиці курсів можуть взагалі відсутні.
Потрібно, проте, показати всі валюти з останнім їх курсом.

Рішення перше (неправильне):

Select val,max(dat),cour from valuta, vcour where
valuta.valuta_id=vcour.valuta_id union ;

Select val, ctod (".."), 0 as cour from valuta where valuta_id not in (select
valuta_id from vcour)

Біда в тому, що функція max, працюючи по всьому діапазону записів, дату-то дає
правильну, зате курс – з останньої за рахунком запису. Якщо курс вводився не в
хронологічному порядку – курс виходить не останньої дати, а останній запис,
хоча сама дата у вибірці – остання.

Рішення в стилі Microsoft – правильне, але не оптимальне.

Select max(dat)as dt,valuta_id from ;
vcour group by valuta_id into cursor qr
Select distinct val,cour,dat from ;
valuta,vcour,qr ;
where valuta.valuta_id=vcour.valuta_id ;
and qr.dt=vcour.dat and ;
qr.valuta_id=valuta.valuta_id ;
union ;
Select distinct val, 1 as cour, ctod ("..") as dat from valuta where;
valuta.valuta_id not in (select distinct valuta_id from vcour);
into cursor vcou

Рішення за дідівськими заповітами. Найшвидше.

Створимо в таблиці курсу валют композитний індекс datcur з виразом
STR(valuta_id,3)+DTOS(dat)
Зробимо функцію Getvcr
Lparameters pr_id,mydat

Local retcr

If order(“vcour”)!=”datcur”
Set order to datcur in vcour
Endif
retcr=0
If empty(mydat)
set exact off
If seek(str(pr_id,3),”vcour”)
retcr=vcour.cour
Endif
Else
If set(“NEAR”)=”OFF”
Set near on
Endif
=seek(str(pr_id,3)+dtos(mydat),”vcour”)
If pr_id=vcour.valuta_id
retcr=vcour.cour
Endif
Set near off
Endif
Return retcr


Тепер достатньо записати Select val, getvcr (valuta.valuta_id) as cour from
valuta – і все.

А хочете курс на конкретну дату – вкажіть її у другому параметрі.

Так і згадується анекдот про двох бичків, старого і молодого. Молодий все
норовив швидко побігти до корівок. Нам же до вподоби принцип старого бичка-
підемо повільно повільно, але поімеем все, що хотіли і може навіть обженемо кого
і молодші.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*