Группировка

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
Senya
Сообщения: 3
Зарегистрирован: 25 апр 2006, 08:40

Группировка

Сообщение Senya » 25 апр 2006, 11:31

Часто возникает задача такого рода: Есть для примера таблица содержащая код обьекта, время и количество. Необходимо для каждой группы объектов найти количество выдававшееся последним. В Аксесе я делал так
Select Cod, Last(Count) from Table
Group by Cod
Order by Max(Time)
Как подобную задачу красиво решить в ibase , как я понимаю агрегатные функции Last() и First() есть только в Аксесе?

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 25 апр 2006, 12:33

Код: Выделить всё

Select t1.Cod, 
  max(t1.fTime), 
  (select fcount 
   from table t2 
   where t1.cod = t2.cod and t2.ftime = max(t1.ftime)) as fcount
from Table t1 
Group by t1.Cod 
Order by 2 

Senya
Сообщения: 3
Зарегистрирован: 25 апр 2006, 08:40

Сообщение Senya » 25 апр 2006, 12:39

Спасибо.

Senya
Сообщения: 3
Зарегистрирован: 25 апр 2006, 08:40

Сообщение Senya » 25 апр 2006, 13:34

Предлоенный запрос
Ivan_Pisarevsky писал(а):

Код: Выделить всё

Select t1.Cod, 
  max(t1.fTime), 
  (select fcount 
   from table t2 
   where t1.cod = t2.cod and t2.ftime = max(t1.ftime)) as fcount
from Table t1 
Group by t1.Cod 
Order by 2 
Представляет обычное внутреннее обьеденение и даже при не очень большой таблице N = 5000 записей делает N^2 вычислений а с учетом того что во внутреннем запросе max(t1.ftime) будет пересчитываться каждый раз - так что даже N^3. Я подождал пол часа но ответа на запрос так и не получил. А в Аксесе почти мгновенно. Не ужели на таком мощном сервере как firebird не найдется более красивого решения. Можно конечно сделать внешнее:
select .. from Table T1 Left Join(Select ..from Table T2 Group by ..) On ...
Но подобные конструкции появились только в FireBird 2.0 , а на нем не работает нужное мне ПО.
Access Forever!!!

eg
Сообщения: 17
Зарегистрирован: 09 ноя 2005, 22:33

Сообщение eg » 25 апр 2006, 14:58

Senya писал(а):...
на таком мощном сервере
...
а какой именно сервер?

Код: Выделить всё

Select t1.Cod, 
  (select first 1 t2.fcount 
   from table t2 
   where t1.cod = t2.cod 
   order by t2.fTime desc) as fcount
from Table t1 
Group by t1.Cod
Senya писал(а): Access Forever!!!
Уря

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 25 апр 2006, 16:55

Код: Выделить всё

oCod = NULL;
otime = NULL;
ocount = NULL;
for Select t1.Cod,t1.ftime, t1.fcount 
from Table t1 
order by cod
into :vCod, :vTime, vcount
do
begin
  if (ocod is NULL) 
  then
  begin
    oCod = vCod; 
    otime = vtime;
    ocount = vcount;
  end
  else
  begin
    if (oCod = vCod)
    then
    begin
    if (otime < vtime)
    then 
    begin 
      otime = vtime;
      ocount = vcount;
    end
end
else
begin
    suspend;
    oCod = vCod; 
    otime = vtime;
    ocount = vcount;
end  
  end
end
    if (oCod = vCod)
    then
begin
if (otime < vtime)
then begin 
    otime = vtime;
    ocount = vcount;
    suspend;
К концу рабочего дня мой мозг родил фоксподобное однопроходное решение, o... - выходные параметры, v... - переменные. Глючить наверно по черному будет, ибо не проверено, совсем... :)

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 25 апр 2006, 17:46

Senya писал(а):Предлоенный запрос
Ivan_Pisarevsky писал(а):

Код: Выделить всё

Select t1.Cod, 
  max(t1.fTime), 
  (select fcount 
   from table t2 
   where t1.cod = t2.cod and t2.ftime = max(t1.ftime)) as fcount
from Table t1 
Group by t1.Cod 
Order by 2 
Представляет обычное внутреннее обьеденение и даже при не очень большой таблице N = 5000 записей делает N^2 вычислений а с учетом того что во внутреннем запросе max(t1.ftime) будет пересчитываться каждый раз - так что даже N^3. Я подождал пол часа но ответа на запрос так и не получил.
Это не внутреннее и не "обьеденение".
Индексы создавать пробовал ?

Ответить