Запрос о почасовой интенсивности (заказов)

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

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

Ответить
Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Запрос о почасовой интенсивности (заказов)

Сообщение Kotъ-Begemotъ » 13 сен 2007, 19:56

А как бы сделать отчёт о распределении заказов по часам? Вот есть таблица Orders в которой есть поля Start и Finish (TimeStamp исесина) и надо получить отчет вида:

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

             00-01   01-02   ...   23-00
05.09.2007   10        3     ...   5
06.09.2007   6         12    ...   1
То есть для каждой даты по каждому часу количество заказов поступивших за этот час...

Сейчас делается через создание промежуточных таблиц

1. СоздаЮ таблицу Matrix со структурой

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

StartDat               EndDat                     Cnt00        Cnt01    ...        Cnt23
05.09.2007 00:00:00    05.09.2007 01:00:00        1            0                    0
05.09.2007 01:00:00    05.09.2007 02:00:00        0            1                    0
.......
05.09.2007 23:00:00    06.09.2007 00:00:00        0            0                    1
2. Выполняю запрос к основной таблице Orders и к этой Matrix

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

select mx.StartDat, mx.EndDat,
          count(od.OrderID)*mx.Cnt00 as Cnt00,
          count(od.OrderID)*mx.Cnt01 as Cnt01,
          .....
          count(od.OrderID)*mx.Cnt23 as Cnt23
from Orders od, Matrix mx
where (od.Start between mx.StartDat and mx.EndDat)
  and (od.Start <> mx.EndDat)
group by mx.StartDat, mx.EndDat
3. Результат сохраняю в таблицу TmpCount

4. СоздаЮ таблицу TmpDat очень простой структуры

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

StartCalc              EndCalc
05.09.2007 23:00:00    06.09.2007 00:00:00
......
15.09.2007 23:00:00    16.09.2007 00:00:00
5. Суммирую

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

select dat.StartCalc,
       sum(Cnt.Cnt00) as Cnt00,
       sum(Cnt.Cnt01) as Cnt01,
       ...
       sum(Cnt.Cnt23) as Cnt23
from TmpDat dat, TmpCount cnt
where (cnt.StartDat between dat.StartCalc and dat.EndCalc)
and cnt.StartDat <> dat.EndCalc
group by dat.StartCalc

И вот кажется мне, что я чего-то недопонимаю, и можно упросить это дело, но чего-то видимо не учитываю... А?

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 13 сен 2007, 22:01

не совсем понял, что делать в случае заказов вида {start = 12:50, finish = 13:10}, но упрощение стоит поискать в аналогии с:

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

select mx.StartDat,
          count(case when extract(hour from mx.StartDat) = 0 then 1 else 0 end) as Cnt00,
          count(case when extract(hour from mx.StartDat) = 1 then 1 else 0 end) as Cnt01,
          .....
          count(case when extract(hour from mx.StartDat) = 23 then 1 else 0 end) as Cnt23,
from...
where...
group by 1

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 13 сен 2007, 23:10

dimitr писал(а):не совсем понял, что делать в случае заказов вида {start = 12:50, finish = 13:10}
Start и Finish поля типа TimeStamp так что тут проблем не будет... За идею спасибо, буду пробовать. К сожалению Local SQL таких выкрутасов не позволял, поэтому и плаваю в них. Но FB2 думаю подобное проглотит легко :)

Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Сообщение Slavik » 13 сен 2007, 23:15

только вместо count надо sum вроде бы... А заказы проходящие через часовую границу обычно учитывают по какому-то одному событию: первому, последнему, середине...

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 13 сен 2007, 23:22

Slavik писал(а):только вместо count надо sum вроде бы... А заказы проходящие через часовую границу обычно учитывают по какому-то одному событию: первому, последнему, середине...
Конечно по одному, в данном случае интересует именно время принятия то есть Start так как отчёт - это почасовая "плотность" поступающих заказов (хотя если добавить еще условие, можно получить отчёт для заказов в результате успешно выполненных)

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 14 сен 2007, 08:28

Slavik писал(а):только вместо count надо sum вроде бы...
да, конечно

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 14 сен 2007, 10:42

dimitr писал(а):
Slavik писал(а):только вместо count надо sum вроде бы...
да, конечно
Можно и Count. Вместо

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

sum(case when extract(hour from mx.StartDat) = 0 then 1 else 0 end) as Cnt00
писать

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

count(case when extract(hour from mx.StartDat) = 0 then 1 else null end) as Cnt00

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 22 сен 2007, 18:28

Час от часу не легче... Теперь надо сделать такой же отчёт только для каждого часа ТРИ значения по различным критериям из таблицы Orders... Причём пока еще под Paradox это надо сделать, соответственно все вкусности типа Case в запросе не катят... 72 поля только под значения... Эх, кадаж я сдохну... :(((

Ответить