Округлить поле даты до следующего получаса в SQL - PullRequest
7 голосов
/ 26 марта 2012

В SQL у меня есть переменная DATE, которую я хочу округлить до следующего доступного получаса (то есть xx: 30). Обратите внимание, что это не должно быть просто до ближайшего получаса.

Вот несколько примеров:

Time                   Expected outcome
2012-03-26 11:25 AM    2012-03-26 11:30 AM
2012-03-26 11:45 AM    2012-03-26 12:30 PM

Есть ли способ сделать это в SQL?

Ответы [ 6 ]

11 голосов
/ 26 марта 2012

Это немного запутанно, но что-то вроде

SELECT round( (date_col - trunc(date_col)) * 48 )/ 48 +
         trunc( date_col )
  FROM dual

должно работать.

SQL> ed
Wrote file afiedt.buf

  1  select round((sysdate - trunc(sysdate)) * 48)/48 + trunc(sysdate),
  2         sysdate
  3*   from dual
SQL> /

ROUND((SYSDATE-TRUNC SYSDATE
-------------------- --------------------
26-mar-2012 14:30:00 26-mar-2012 14:35:30
  • TRUNC(date_col) сокращает время до полуночи.
  • date_col - trunc(date_col) возвращает часть дня, прошедшего с полуночи.
  • Умножение на 48 дает количество получасовых приращений
  • Округление, которое дает вам ближайшие полчаса
  • Тогда деление на 48 дает вам долю дня, которую можно прибавить к trunc(date_col)
4 голосов
/ 26 марта 2012

Дали +1 к ответу Джастина за оригинальность.

Если вы хотите более педантичный (или, возможно, более понятный или поддерживаемый) подход,

select case when to_number(to_char(sysdate,'mi')) > 30
       then trunc(sysdate,'mi') + ((60 - to_number(to_char(sysdate,'mi')) +30)/1440)
       else trunc(sysdate,'mi') + (30 - to_number(to_char(sysdate,'mi')))/1440 end
from dual

Ятолько добавив это, так как это может быть более адаптируемым подходом, если вам нужно сделать что-то похожее с другими числами, например, через 45 минут после часа.Вы бы просто заменили три 30-х на 45-и, и все, и вы уходите.

Для производительности, но для вашей конкретной проблемы - Джастин - настоящий победитель.

4 голосов
/ 26 марта 2012

Вот небольшая поправка к ответу Джастина, который, я думаю, дает желаемые результаты:

WITH thedate AS (SELECT trunc(SYSDATE)+6.5/48 thedate FROM dual)
select round((thedate - trunc(thedate)) * 24 - 1/(24*3600))/24 + trunc(thedate)+1/48,
          theDATE
     from thedate;

По сути, это округляет до ближайшего часа (после вычитания секунды, чтобы предотвратить округление, когда вы точно наполчаса), затем добавляет полчаса.

2 голосов
/ 02 апреля 2014

Чтобы получить следующие полчаса, измените решение Джастина Кейва, изменив ROUND на CEIL:

SELECT CEIL( (date_col - trunc(date_col)) * 48 )/ 48 +
         trunc( date_col )
  FROM dual

ROUND перейдет к ближайшему (вверх иливниз), CEIL поднимается до , затем (всегда вверх). FLOOR будет переходить к предыдущему (всегда вниз).

Чтобы ответить на вопрос Майкла Бротона о возможности обеспечения:

48 - это число "половинычасов "в день.Чтобы изменить период, замените оба экземпляра на:

60/x * 24

, где x - количество минут в требуемом периоде.

Например, каждые 10 минут = (60/10)* 24 = 144.

Надеюсь, это поможет!

2 голосов
/ 27 марта 2012

Мой код делает это с помощью функции ROUND, чтобы округлить до ближайшего часа, а затем добавить полчаса

WITH thedate AS
     (SELECT TO_DATE ('2012-03-26 11:20 AM', 'YYYY-MM-DD HH:MI AM') mydate
        FROM DUAL)
SELECT mydate,
       TO_CHAR (ROUND (mydate, 'HH') + 1 / 48,
                'YYYY-MM-DD HH:MI AM'
               ) "Rounded Date"
  FROM thedate;

Надеюсь, это поможет

0 голосов
/ 22 мая 2014

упрощенно (надеюсь) ...

select 
  case
    when to_number(to_char(sysdate,'mi')) <= 30
      then trunc(sysdate,'hh24') + 30/1440
      else trunc(sysdate,'hh24') + 1/24
  end
from dual;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...