我在date_range表中有两个日期时间记录“start_date”和“end_date”。
我想每小时间隔每小时插入一行,加上一个持续时间(以小时为单位)的列,以便我的结果返回如下:
e.g。 start_date = 2016/09/01 21:12:00和end_date = 2016/09/02 01:30:00
Date Hour Duration
2016/09/01 21 0.8
2016/09/01 22 1
2016/09/01 23 1
2016/09/02 00 1
2016/09/02 01 0.5
答案 0 :(得分:0)
You can do it with procedure like this:
first I prepare your data;
create table date_range
(
start_date date,
end_date date
);
create table result_table
(
date_ varchar2(10),
hour_ varchar2(2),
duration number
);
insert into date_range
select to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'),to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') from dual ;
commit;
second I create your procedure;
CREATE OR REPLACE procedure get_dates
AS
rn number:=0;
temp varchar2(10);
BEGIN
select
ceil(24* ( end_date-start_date ))-1
into rn
from
date_range;
FOR i IN 0..rn
LOOP
temp:=i||'/24';
EXECUTE IMMEDIATE '
insert into result_table
select
to_char(start_date+'||temp||',''yyyy/mm/dd'')date_,
to_char(start_date+'||temp||',''hh24'')hour_,
case
when '||i||'=0
then 1-to_number(to_char(start_date+'||temp||',''mi''))/60
when '||i||'='||rn||'
then 1-to_number(to_char(end_date+'||temp||',''mi''))/60
else 1
end duration
from
date_range ';
commit;
END LOOP;
END get_dates;
thirdly I execute procedure ;
begin
get_dates();
end;
finally I see the expected result ;
select
* from
result_table;
DATE_ HOUR_ DURATION
2016/09/01 21 0,8
2016/09/01 22 1
2016/09/01 23 1
2016/09/02 00 1
2016/09/02 01 0,5
答案 1 :(得分:0)
select case when lvl=mn then (trunc(frst)+1)- frst
when lvl=mx then lst-trunc(lst)
else 1
end ,a.*
from
(
select frst,lst,sonuc,lvl,first_value(lvl)over() mn,last_value(lvl) over() mx
from
(select to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss') frst,
to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') lst,
(to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') - to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'))*24 sonuc from dual) a
,
( select level lvl
from dual
connect by level <=
(select
case when (to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') - to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'))*24>
trunc((to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') - to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'))*24)
then trunc((to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') - to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'))*24)+1
else trunc((to_date('2016/09/02 01:30:00','YYYY/MM/DD hh24:mi:ss') - to_date('2016/09/01 21:12:00','YYYY/MM/DD hh24:mi:ss'))*24)
end
from dual)
) b
)a
答案 2 :(得分:0)
这是一个简单的SQL解决方案(最好尽可能避免使用PL / SQL而不是太复杂)。它使用自Oracle 11.1以来可用的递归因子子查询。我创建了几个&#34;行&#34;测试数据,以显示这可能同时对多对输入有效。请注意,第一个子查询不是解决方案的一部分 - 您将使用实际的表和列名称或任何输入源替换它(以及实际解决方案中对它的引用,这是查询的其余部分)。
还要注意&#34; date&#34;和&#34;小时&#34;是Oracle中的保留字,它们不应该用作列名(在输出中或其他任何地方)。我改为使用dt
和hr
。
with
date_range ( row_id, start_date, end_date ) as (
select 101, to_date('2016/09/01 21:12:00', 'yyyy/mm/dd hh24:mi:ss'),
to_date('2016/09/02 01:30:00', 'yyyy/mm/dd hh24:mi:ss') from dual union all
select 102, to_date('2016/09/02 21:00:00', 'yyyy/mm/dd hh24:mi:ss'),
to_date('2016/09/02 22:00:00', 'yyyy/mm/dd hh24:mi:ss') from dual union all
select 103, to_date('2016/09/01 15:00:00', 'yyyy/mm/dd hh24:mi:ss'),
to_date('2016/09/01 15:30:00', 'yyyy/mm/dd hh24:mi:ss') from dual union all
select 104, to_date('2016/09/01 21:12:00', 'yyyy/mm/dd hh24:mi:ss'),
to_date('2016/09/01 21:30:00', 'yyyy/mm/dd hh24:mi:ss') from dual
),
rec ( row_id, from_time, to_time, end_date ) as (
select row_id, start_date,
least(end_date, trunc(start_date, 'hh') + 1/24), end_date
from date_range
union all
select row_id, to_time, least(end_date, to_time + 1/24), end_date
from rec
where end_date > from_time + 1/24
)
select row_id,
to_char(from_time, 'yyyy/mm/dd') as dt,
to_char(from_time, 'hh24') as hr,
round(24 * (to_time - from_time), 2) as duration
from rec
order by row_id, from_time
;
<强>输出强>:
ROW_ID DT HR DURATION
---------- ---------- -- ----------
101 2016/09/01 21 .8
101 2016/09/01 22 1
101 2016/09/01 23 1
101 2016/09/02 00 1
101 2016/09/02 01 .5
102 2016/09/02 21 1
103 2016/09/01 15 .5
104 2016/09/01 21 .3
8 rows selected