I'm not sure how happy 8i will be with this, but you can split the records up into hour (or partial hour) chunks with a hierarchical query like this:
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');
... where t42 is a table populated as in your first image. That gives:
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
You can then use that as a CTE, or as I don't think 8i knows about CTEs an inline view, and calculate the difference between each time and it's proportion against the original range, and divide the tally by that:
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; but that's 11gR2 so doesn't mean it'll work in 8i. I don't have such an ancient version to test on unfortunately.
If your table has an ID column then use that for the connect by prior
clause - I've had to use firstoccurrence
and hope it's unique. You may also need to use dbms_random.value
instead of sys_guid()
- an non-deterministic function will do though.