如何在Oracle SQL中将时间间隔四舍五入到第二天?
select apppackage
, numtodsinterval(
sum( trunc(extract (day from (periods)) * 86400
+ extract (hour from (periods)) *3600
+ extract (minute from (periods))*60
+ extract (second from (periods)))
), 'SECOND') as retention_period
, count(apppackage) as users
from retentions
where apppackage = 'com.Freesoul.Rotter'
group by apppackage;
此输出为
'com.Freesoul.Rotter''+2969 04:32:47.000000''3'
期望的输出是
'com.Freesoul.Rotter''2970''3'
但是如果查询的输出是
'com.Freesoul.Rotter''+2969 00:00:00.000000''3'
那么所需的输出是
'com.Freesoul.Rotter''2969''3'
列期为INTERVAL DAY(9)至SECOND(6)类型 而且我不介意将tentional_period更改为数字数据类型。
如果有人可以建议更改查询以获得所需的输出,我将不胜感激。
答案 0 :(得分:2)
求和的结果以秒为单位,因此您根本不需要将其转换为间隔。只需除以60 * 60 * 24,就可以在几天之内得到答案,然后用ceil()
将其四舍五入:
select apppackage
, ceil(sum( trunc(extract (day from (periods)) * 86400
+ extract (hour from (periods)) *3600
+ extract (minute from (periods))*60
+ extract (second from (periods)))
) / 86400) as retention_period
, count(apppackage) as users
from retentions
where apppackage = 'com.Freesoul.Rotter'
group by apppackage;
在两种情况下,在CTE中使用人工数据进行演示只是为了模仿您的预期结果:
-- CTE for sample data
with retentions (apppackage, periods) as (
select 'com.Freesoul.Rotter', interval '+2967 04:32:47.000000' day(9) to second(6) from dual
union all
select 'com.Freesoul.Rotter', interval '1' day from dual
union all
select 'com.Freesoul.Rotter', interval '1' day from dual
union all
select 'com.Freesoul.XYZ', interval '+2967 00:00:00.000000' day(9) to second(6) from dual
union all
select 'com.Freesoul.XYZ', interval '1' day from dual
union all
select 'com.Freesoul.XYZ', interval '1' day from dual
)
-- actual query
select apppackage
, ceil(sum( trunc(extract (day from (periods)) * 86400
+ extract (hour from (periods)) *3600
+ extract (minute from (periods))*60
+ extract (second from (periods)))
) / 86400) as retention_period
, count(apppackage) as users
from retentions
where apppackage = 'com.Freesoul.Rotter'
-- extra clause for dummy data
or apppackage = 'com.Freesoul.XYZ'
group by apppackage;
APPPACKAGE RETENTION_PERIOD USERS
------------------- ---------------- ----------
com.Freesoul.XYZ 2969 3
com.Freesoul.Rotter 2970 3
您的预期输出显示一个纯数字。如果您实际上希望将其作为一个间隔,但作为整个天数,则只需将ceil'd数传递到numtodsinterval
或更简单(通常出于某种原因通常更快)乘以interval '1' day
。>
具有相同的伪数据:
select apppackage
, ceil(sum( trunc(extract (day from (periods)) * 86400
+ extract (hour from (periods)) *3600
+ extract (minute from (periods))*60
+ extract (second from (periods)))
) / 86400) * interval '1' day as retention_period
, count(apppackage) as users
...
APPPACKAGE RETENTION_PERIOD USERS
------------------- --------------------- ----------
com.Freesoul.XYZ +2969 00:00:00.000000 3
com.Freesoul.Rotter +2970 00:00:00.000000 3
正如@mathguy指出的那样,您可能不需要或不需要trunc()
呼叫;即从每个周期中减去小数秒,然后再将它们相加,这听起来微不足道,但很容易影响您获得的结果。
答案 1 :(得分:0)
怎么样?
CASE WHEN numtodsinterval(extract (day from periods), 'DAY') = periods THEN
extract (day from periods)
ELSE
extract (day from periods) + 1
END