oracle查询按小时分组日期差异

时间:2014-05-22 20:35:32

标签: sql oracle

我希望得到一些帮助来编写一些我自己没有成功的SQL。

我有一张包含数据的表格:

ID    StartDate             EndDate
1     01/01/2000 04:30 AM   01/02/2000 06:15 AM
2     01/03/2000 06:10 AM   01/03/2000 07:00 AM

我需要得到以下内容:

Hour24     Minutes
04         30
05         60
06         65
07         60

换句话说,按小时分割日期范围。然后按小时汇总每个范围。 我的数据库是Oracle 11G R2,我担心由于情况我无法使用PL / SQL。

非常感谢你的帮助!

3 个答案:

答案 0 :(得分:0)

基本上,要解决此问题,您只需要一个数字列表。

with nums as (
      select 0.0 as n from dual
      union all
      select n + 1
      from nums
      where n < 100
    )
select trunc(t.startdate + n * 1/ 24, 'hh'),
       sum((case when trunc(t.startdate + n * 1/24, 'hh') = trunc(t.startdate, 'hh')
                 then 60 - extract(minute from startdate)
                 else 0
            end) +
           (case when trunc(t.startdate + n * 1/24, 'hh') > trunc(t.startdate, 'hh') and
                      trunc(t.startdate + n * 1/24, 'hh') < trunc(t.enddate, 'hh')
                 then 60
                 else 0
            end) +
           (case when trunc(t.startdate + n * 1/24, 'hh') = trunc(t.enddate, 'hh')
                 then extract(minute from enddate)
                 else 0
            end)
           ) as minutes
from table t join
     nums n
     where trunc(t.startdate + n * 1/24, 'hh') <= t.enddate;

这适用于日期长达100小时的差异。您可以根据需要调整100。您甚至可以使用子查询来获得正确的最大值。

有些技巧可以简化逻辑。我认为上述逻辑是最清楚的。它循环工作时间。如果比较的小时是第一个小时,请使用60分钟。如果是最后一个,请使用分钟。否则,请使用60。

答案 1 :(得分:0)

作为第一步,您需要一个包含24行的表。不好的例子:

从all_objects中选择rownum rnum,其中rownum&lt; 25

然后你将该表加入到你的表中,条件是rnum小时在startdate和enddate之间

在select和from之间你会把rnum和一个公式用来计算该特定记录中的分钟数和rnum小时

然后你将该查询包装在另一个具有GROUP BY构造的查询中。

答案 2 :(得分:0)

如果您的日期时间范围可以超过一天,正如您的示例数据所示,那么它们可能会占用超过60分钟的一小时。例如,我们有一个荒谬的过程,需要48个小时才能完成,因此在检查时,只需说出小时6,基于24小时计数器的查询将返回60,而实际上他们可能需要返回120。

with hours as (
  select trunc(sysdate, 'hh') - ((rownum - 1) / 24) as testhour
  from dual connect by rownum <= (trunc(sysdate, 'hh') - (trunc(sysdate, 'mm') - (1 / 24))) * 24
)
select
  to_char(h.testhour, 'hh24') as Hour24,
  round(sum((least(t.stopdatetime, h.testhour + (1/24)) - greatest(t.startdatetime, h.testhour)) * 1440)) Minutes
from
  datetimes t,
  hours h
where
  t.stopdatetime >= trunc(sysdate, 'mm')
  and (
    h.testhour between t.startdatetime and t.stopdatetime
    or h.testhour = trunc(t.startdatetime, 'hh')
  )
group by
  to_char(h.testhour, 'hh24')
order by 1
;

此查询应处理这些情况,但在其当前表单中运行需要更长时间;它会返回每个小时的日期时间,从本月的第一个小时到当前小时。