Oracle SQL интервал времени округления до следующего дня - PullRequest
0 голосов
/ 21 ноября 2018

Как округлить временной интервал до следующего дня в 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) TO Second (6), и я выиграл 'Не возражайте, если retention_period изменяется на тип данных number.

Буду благодарен, если кто-нибудь может предложить изменение в моем запросе для достижения желаемого результата.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Результат вашей суммы в секундах, поэтому вам не нужно вообще преобразовывать ее в интервал.Просто разделите на 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();это убирает доли секунды из каждого периода перед их суммированием, что звучит несущественно, но может легко повлиять на полученный результат.

0 голосов
/ 21 ноября 2018

Как насчет этого?

CASE WHEN numtodsinterval(extract (day from periods), 'DAY') = periods THEN 
    extract (day from periods)
ELSE
    extract (day from periods) + 1
END
...