舍入到前2小时窗口Oracle SQL

时间:2016-07-14 20:44:02

标签: sql oracle datetime

我正在尝试将日期(包含时间戳的日期数据类型)舍入到前2小时块。例如13:23 - > 12:00,18:12 - > 18:00

我使用MOD函数在MySQL中工作:

DATE_ADD(DATE(DATE_ADD(created_at, INTERVAL - 7 HOUR)), INTERVAL HOUR(DATE_ADD(created_at, INTERVAL - 6 HOUR)) - MOD(HOUR(DATE_ADD(created_at, INTERVAL - 6 HOUR)), 2) HOUR) AS Window_Start

**复杂性增加,因为我也正在改变时间a)以纠正7小时的时区差异和b)因为我需要在分组之前将时间偏移1小时。但这不是问题所在。

但我无法让它在Oracle平台上运行。具体来说,我似乎无法提取时间小时作为输入MOD()的数字。我一直在尝试使用CAST,TO_TIMESTAMP和TO_CHAR,但似乎没有任何效果。通常的错误是“数据类型不一致”。

EXTRACT仅适用于时间戳类型,而不是日期。并且TO_TIMESTAMP仅适用于字符串。但是EXTRACT(TO_TIMESTAMP(TO_CHAR)(也不起作用。

我确信有一种更简单的方法可以做到这一点......

4 个答案:

答案 0 :(得分:0)

在Oracle中,一种方法是使用日期算法。例如:

select date '2000-01-01' + floor((sysdate - date '2000-01-01') * (24 / 2)) / (24 / 2)
from dual;

" 24"是一天几个小时。 " 2"是你要截断的两个小时的时间段。

答案 1 :(得分:0)

我不确定这是答案,但它会给你一个兔子洞来追逐:

select sysdate as curr_dt, to_date(to_char(sysdate - interval '2' hour, 'yyyy-mm-dd HH24')) as two_hours_ago from dual;

希望它有所帮助!

答案 2 :(得分:0)

要以数字格式获取小时,这将有效。

从双重选择TO_NUMBER(TO_CHAR(SYSDATE,'HH'))

您可以使用此日期格式DD / MM / YYYY HH:MI:SS的时间戳部分单独选择每个部分。

答案 3 :(得分:0)

前段时间我写了这个通用函数:

CREATE FUNCTION MakeInterval(ts IN TIMESTAMP, roundInterval IN INTERVAL DAY TO SECOND) RETURN TIMESTAMP DETERMINISTIC IS
    denom INTEGER;
BEGIN
    IF roundInterval >= INTERVAL '1' HOUR THEN
        denom := EXTRACT(HOUR FROM roundInterval);
        IF MOD(24, denom) <> 0 THEN
            RAISE VALUE_ERROR;
        END IF;
        RETURN TRUNC(ts) + TRUNC(EXTRACT(HOUR FROM ts) / denom) * denom * INTERVAL '1' HOUR;
    ELSIF roundInterval >= INTERVAL '1' MINUTE THEN
        denom := EXTRACT(MINUTE FROM roundInterval);
        IF MOD(60, denom) <> 0 THEN
            RAISE VALUE_ERROR;
        END IF;
        RETURN TRUNC(ts, 'hh') + TRUNC(EXTRACT(MINUTE FROM ts) / denom) * denom * INTERVAL '1' MINUTE;
    ELSE
        denom := EXTRACT(SECOND FROM roundInterval);                
        IF MOD(60, denom) <> 0 THEN
            RAISE VALUE_ERROR;
        END IF;
        RETURN TRUNC(ts, 'mi') + TRUNC(EXTRACT(SECOND FROM ts) / denom) * denom * INTERVAL '1' SECOND;
    END IF;
END MakeInterval;

在您的情况下,用法是

SELECT MakeInterval(created_at, INTERVAL '2' HOUR) 
FROM ...

但也许这对你的情况来说太过分了,没有这个功能的用法就是:

SELECT TRUNC(created_at) + TRUNC(EXTRACT(HOUR FROM created_at) / 2) * 2 * INTERVAL '1' HOUR
FROM ...