for flooders
:: Главная :: Решения :: Статьи :: Сайт М. Дроздова :: Файловый архив :: Книга по VFP 9 :: Русский Help Online :: OFF-LINE Форум
   Л и с о в о д ы   в с е х   с т р а н,  о б ъ е д и н я й т е с ь !!!  

Список Форумов  :: Игры Разума
   :: Помощь сайту :: 

Можно ли в этой задачке обойтись только реляционными командами?
Вячеслав Клепинин
Автор

Сообщений: 1597
Откуда: Санкт-Петербург
Дата: 22.03.07 10:33:58ОтветитьЦитировать
Что-то тихо здесь стало...
Вот ещё одна задачка, которую мне не удалось решить, используя только реляционные команды. Может, кто сумеет?

Мониторинг рекламы. В БД ведётся список рекламных модулей, опубликованных в прессе.
Существует выборка за определённый временной период вида:

modules(id_smi, id_org, smod, cena, data)

где: id_smi - ID газеты, в которой опубликована реклама; id_org - ID рекламодателя; smod - площадь модуля; cena - его стоимость; data - дата публикации.

Выбранный период разбит пополам, т.е. появляются предыдущий и текущий периоды; значение даты половины интервала задаётся в переменной.

Нужно получить результирующий курсор вида:

result(id_smi, org, delta_org, smod, delta_smod, mod, delta_mod, cena, delta_cena)

где по каждому СМИ:
org - количество рекламодателей за текущий период;
delta_org - изменение количества рекламодателей по отношению к предыдущему периоду;
smod - общая площадь рекламы за текущий период, delta_smod - изменение площади рекламы по отношению к предыдущему периоду;
mod - количество рекламных модулей за текущий период

Ну и так далее.



Исправлено: Вячеслав Клепинин, 22.03.07 10:42
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
PaulWist

Сообщений: 13046
Дата: 22.03.07 11:14:06ОтветитьЦитировать
Слава, ну скрипт бы написал с заполнением таблички, что бы только select добавить надо было.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
leonid

Сообщений: 2585
Откуда: Рига
Дата: 22.03.07 12:14:22ОтветитьЦитировать
Что-то в таком духе?
create cursor rekl (id_smi i, id_org i, smod N(4), cena N(6,2), data D)  
  rand(-1)  
  local m.i, m.mindat, m.maxdat, m.middat  
  m.mindat=date()-90  
  m.maxdat=date()  
  for i=1 to 1000  
  	insert into rekl values ;  
  		(rnd(1,5), rnd(1,100), rnd(30,300), rnd(200,2000)/100, ;  
  			m.mindat+rnd(0,m.maxdat-m.mindat))  
  next  
    
  m.middat=m.mindat+45  
    
  select id_smi, count(distinct id_org) as orgp, ;  
  	sum(smod) as smodp, sum(cena) as cenap from rekl ;  
  	where data<=m.middat group by 1 into cursor tmp1  
    
  select id_smi, count(distinct id_org) as org, ;  
  	sum(smod) as smod, sum(cena) as cena from rekl ;  
  	where data>m.middat group by 1 into cursor tmp2  
    
  select nvl(t1.id_smi, t2.id_smi) as id_smi, ;  
  	nvl(t2.org,00000) as org, ;  
  	nvl(t2.org,00000)-nvl(t1.orgp,00000) as delta_org, ;  
  	nvl(t2.smod,00000) as smod, ;  
  	nvl(t2.smod,00000)-nvl(t1.smodp,00000) as delta_smod, ;  
  	nvl(t2.cena,00000) as cena, ;  
  	nvl(t2.cena,00000)-nvl(t1.cenap,00000) as delta_cena ;  
  	from tmp1 t1 full outer join tmp2 t2 on t1.id_smi=t2.id_smi  
    
  function rnd  
  lparam m.imin, m.imax  
  return min(int(rand()*(m.imax-m.imin+1))+m.imin, m.imax)
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
Вячеслав Клепинин
Автор

Сообщений: 1597
Откуда: Санкт-Петербург
Дата: 22.03.07 13:42:23ОтветитьЦитировать
leonid, спасибо!

Как-то не пришло в голову использовать full join. Я его практически по жизни использовал пару раз, не больше...
По времени выполнения разницу с моим кодом не поймать, так как результирующие курсоры очень маленькие.

Ещё раз спасибо! Пошёл переписывать код...
И заодно подучить Select .. SQL



Исправлено: Вячеслав Клепинин, 22.03.07 13:42
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
leonid

Сообщений: 2585
Откуда: Рига
Дата: 22.03.07 13:54:52ОтветитьЦитировать
Вячеслав Клепинин
Ещё раз спасибо!
Не за что.
Цитата:
full join. Я его практически по жизни использовал пару раз, не больше...
Я его тоже очень редко использовал, но именно в задачах, где сравниваются два периода.
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
Вячеслав Клепинин
Автор

Сообщений: 1597
Откуда: Санкт-Петербург
Дата: 22.03.07 14:08:16ОтветитьЦитировать
Для небольших объёмов данных это вполне подходит, меньше кода получается.
Но для больших... Так как в результате FULL JOIN мы получаем декартово произведение, то время выполнения будет пропорционально произведению записей в обеих курсорах. У нас мониторятся 40 газет, поэтому промежуточная выборка содержит всего 1600 записей, и это обрабатывается практически мгновенно.
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
leonid

Сообщений: 2585
Откуда: Рига
Дата: 22.03.07 15:57:00ОтветитьЦитировать
Да нет, в таком варианте нет никакого декартова произведения
full outer join tmp2 t2 on t1.id_smi=t2.id_smi
Просто берется inner join и к нему добляются хвосты от обеих таблиц, не имеющих соответствия. Я сейчас запустил приведенный пример на 100000, сработало очень быстро, с декартовым произведением застряло бы.
Ratings: 0 negative/0 positive

Re: Можно ли в этой задачке обойтись только реляционными командами?
Igor Korolyov

Сообщений: 32363
Дата: 04.04.07 01:18:26ОтветитьЦитировать
Hi Вячеслав!

Декартово произведение появится если совсем убрать условие связи - т.е. ON (чего синтаксис с JOIN не позволяет - тока если по старинке через запятую источники перечислять) или если условие связыает поля, которые в обеих таблицах во ВСЕХ записях идентичны (что встречается конечно очень редко). Во всех прочих случаях не получится декартова произведения - т.е. объём выборки не будет составлять N*M записей (где N и M - объёмы "объединяемых" таблиц).


------------------
WBR, Igor
Ratings: 0 negative/0 positive



Извините, только зарегистрированные пользователи могут писать в этом форуме.

On-line: 46 avantum  and Guests: 45


© 2000-2019 Fox Club 
Яндекс.Метрика