我怎样才能在一小时内分割一行数据?

时间:2015-11-17 16:26:11

标签: sql oracle

我需要在一小时的时间内将每行数据分开,给出一小时的差异。 我从以下数据开始:

enter image description here

我想输出这个结果:

enter image description here

Tally是两个日期之间事件发生的次数,New_date将是每个段的开始,new_tally是原始计数的一个除以每个段的时间比例。

我已经尝试在另一个question中执行sqlfiddle,但是我收到以下错误:

  

ORA-01436:用户数据中的CONNECT BY循环

来自小提琴的确切代码:

    create table log_table
        ( dt1 date, dt2 date
        );

    insert into log_table values(sysdate,sysdate-5/24);

    select greatest(dt2, trunc(dt2+(level-1)/24, 'hh24')), least(dt1, trunc(dt2+(level)/24, 'hh24'))
    from log_table connect by level <= floor((dt1-dt2)*24)+1;

这可能与我在Oracle 8i数据库中尝试此事实有关。我也一直试图理解分层查询是如何工作的,但我发现它们真的很复杂。

有人能给我一个例子并解释发生了什么吗?提前谢谢。

内加。

1 个答案:

答案 0 :(得分:1)

我不确定8i对此有多开心,但您可以使用以下分层查询将记录分成小时(或部分小时)块:

select firstoccurrence, lastoccurrence, tally,
  greatest(firstoccurrence,
    trunc(firstoccurrence, 'HH24') + (level - 1) / 24) as new_start,
  least(lastoccurrence,
    trunc(firstoccurrence, 'HH24') + level / 24) as new_end
from t42
connect by firstoccurrence = prior firstoccurrence
and prior sys_guid() is not null
and trunc(firstoccurrence, 'HH24') + (level - 1) / 24
  <= trunc(lastoccurrence, 'HH24');

...其中t42是填充在第一张图片中的表格。这给了:

FIRSTOCCURRENCE     LASTOCCURRENCE      TALLY NEW_START           NEW_END           
------------------- ------------------- ----- ------------------- -------------------
2014-12-04 11:33:16 2014-12-04 11:33:36     1 2014-12-04 11:33:16 2014-12-04 11:33:36
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 11:41:46 2014-12-30 12:00:00
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 12:00:00 2014-12-30 13:00:00
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 13:00:00 2014-12-30 14:00:00
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 14:00:00 2014-12-30 15:00:00
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 15:00:00 2014-12-30 16:00:00
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 16:00:00 2014-12-30 16:23:08

然后您可以将其用作CTE,或者我认为8i不知道CTE是内联视图,并计算每个时间与原始范围的比例之间的差异,并将该分数除以:< / p>

select firstoccurrence, lastoccurrence, tally, new_start, new_end,
  to_number(to_char(new_start, 'HH24')) as new_hour,
  tally / ((lastoccurrence - firstoccurrence) / (new_end - new_start)) as new_tally
from (
  select firstoccurrence, lastoccurrence, tally,
    greatest(firstoccurrence,
      trunc(firstoccurrence, 'HH24') + (level - 1) / 24) as new_start,
    least(lastoccurrence,
      trunc(firstoccurrence, 'HH24') + level / 24) as new_end
  from t42
  connect by firstoccurrence = prior firstoccurrence
  and prior sys_guid() is not null
  and trunc(firstoccurrence, 'HH24') + (level - 1) / 24
    <= trunc(lastoccurrence, 'HH24')
);

FIRSTOCCURRENCE     LASTOCCURRENCE      TALLY NEW_START           NEW_END             NEW_HOUR   NEW_TALLY
------------------- ------------------- ----- ------------------- ------------------- -------- -----------
2014-12-04 11:33:16 2014-12-04 11:33:36     1 2014-12-04 11:33:16 2014-12-04 11:33:36       11    1.000000
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 11:41:46 2014-12-30 12:00:00       11     .453619
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 12:00:00 2014-12-30 13:00:00       12    1.492714
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 13:00:00 2014-12-30 14:00:00       13    1.492714
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 14:00:00 2014-12-30 15:00:00       14    1.492714
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 15:00:00 2014-12-30 16:00:00       15    1.492714
2014-12-30 11:41:46 2014-12-30 16:23:08     7 2014-12-30 16:00:00 2014-12-30 16:23:08       16     .575524

SQL Fiddle demo;但那是11gR2所以并不意味着它可以在8i中运行。不幸的是,我没有这么古老的版本进行测试。

如果你的表有一个ID列,那么对connect by prior子句使用它 - 我必须使用firstoccurrence并希望它是唯一的。您可能还需要使用dbms_random.value代替sys_guid() - 但非确定性函数会执行此操作。