группировка по 5 минут без пропусков

s_petrov
Дата: 22.10.2015 04:30:46
Добрый день!

Имеется запрос к большой таблице, группирующий данные по 5 минут, а-ля
with t as (
      select to_date('2015-10-17 01:01:21','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:03:25','yyyy-mm-dd hh24:mi:ss') d from dual
union select to_date('2015-10-17 01:16:21','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:23:44','yyyy-mm-dd hh24:mi:ss') d from dual
union select to_date('2015-10-17 01:24:45','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:33:25','yyyy-mm-dd hh24:mi:ss') d from dual
)
select count(*), trunc(t.d,'HH24')+trunc(to_char(t.d,'MI')/5)/(12*24)
from t
where d between to_date('2015-10-17 01:00:00','yyyy-mm-dd hh24:mi:ss') and to_date('2015-10-17 01:30:00','yyyy-mm-dd hh24:mi:ss')
group by trunc(t.d,'HH24')+trunc(to_char(t.d,'MI')/5)/(12*24)
order by 2

на выходе получаем таблицу с "провалами":
cntdate
22015-10-17 01:00:00
12015-10-17 01:15:00
22015-10-17 01:20:00

в то время как потребовались данные в виде
cntdate
22015-10-17 01:00:00
02015-10-17 01:05:00
02015-10-17 01:10:00
12015-10-17 01:15:00
22015-10-17 01:20:00


что где в запросе теперь нужно изменить?
Добрый Э - Эх
Дата: 22.10.2015 06:15:42
s_petrov,

если данных нет, то единственный вариант показать их - сгенерировать.
на уровне запроса генерацию строк можно сделать посредством рекурсивного WITH, иерархических расширений (start with ... connect by ... prior), либо посредством обращения к таблице с нужным кол-вом записей...
s_petrov
Дата: 22.10.2015 07:41:30
эм.... спасибо за ответ, но нет ли возможности привести хотя бы схематический пример для не сильно одаренных, куда этот рекурсивный with с иерархическими расширениями вставлять и как это будет выглядеть?
Opus Magnum
Дата: 22.10.2015 09:27:37
s_petrov,

По Вашему случаю нет сейчас времени писать, возможно, такой набросок Вам поможет чем-нибудь.

+ Запросик с with

WITH t
     AS (    SELECT ROWNUM
               FROM DUAL
         CONNECT BY ROWNUM < 100)
SELECT *
  FROM DUAL JOIN t ON 1 = 1

GOSTь
Дата: 22.10.2015 12:18:43
Добрый Э - Эх
если данных нет, то единственный вариант показать их - сгенерировать.
на уровне запроса генерацию строк можно сделать посредством рекурсивного WITH, иерархических расширений (start with ... connect by ... prior), либо посредством обращения к таблице с нужным кол-вом записей...

with t as (
      select to_date('2015-10-17 01:01:21','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:03:25','yyyy-mm-dd hh24:mi:ss') d from dual
union select to_date('2015-10-17 01:16:21','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:23:44','yyyy-mm-dd hh24:mi:ss') d from dual
union select to_date('2015-10-17 01:24:45','yyyy-mm-dd hh24:mi:ss') d from dual 
union select to_date('2015-10-17 01:33:25','yyyy-mm-dd hh24:mi:ss') d from dual
), m as (
--  таблица с нужным кол-вом записей (количество пятиминуток)
select date'2015-10-17'+(level-1)/(12*24) step_begin,
       date'2015-10-17'+(level)/(12*24)-(1/(24*60*60)) step_end
from   dual
connect by level <= 24*12
)
select count(t.d) cnt, m.step_begin, m.step_end
from   m left join t
on (t.d between m.step_begin and m.step_end)
where m.step_end between to_date('2015-10-17 01:00:00','yyyy-mm-dd hh24:mi:ss') 
                     and to_date('2015-10-17 01:30:00','yyyy-mm-dd hh24:mi:ss')
group by m.step_begin, m.step_end
order by m.step_begin