Oracle SQL向上舍入时间间隔到第二天

时间:2018-11-21 15:49:01

标签: sql oracle oracle11g rounding

如何在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更改为数字数据类型。

如果有人可以建议更改查询以获得所需的输出,我将不胜感激。

2 个答案:

答案 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