Завершить поле даты до следующего получаса в SQL

В 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 ответов

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

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

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-ю и ушли.

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


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

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)


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

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;

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


Мой код делает это, используя функцию 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;

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


Чтобы получить следующие полчаса, измените решение Justin Cave, изменив 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.

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


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

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;

licensed under cc by-sa 3.0 with attribution.