在Informix SQL中将时间戳舍入到一整小时

在Informix SQL中将时间戳舍入到一整小时,sql,time,informix,Sql,Time,Informix,我有一个数据库表,它有一个名为dlv_tm的列,其中包含hh:mm:ss格式的时间戳 大多数时间戳都是整小时,例如09:00:00、11:00:00等,但有些时间戳故意偏移一分钟,例如08:59:00、10:59:00等,以区分不同的原因 但是,这意味着从这个表中提取数据会得到非常分散的结果,我希望忽略这些偏移量来聚合数据,即,将具有一分钟偏移量的记录视为不存在偏移量 换句话说,当我遇到一个时间戳为08:59:00的记录时,我想拉一个时间戳为09:00:00的记录 我尝试了不同的方法,使用CAS

我有一个数据库表,它有一个名为dlv_tm的列,其中包含hh:mm:ss格式的时间戳

大多数时间戳都是整小时,例如09:00:00、11:00:00等,但有些时间戳故意偏移一分钟,例如08:59:00、10:59:00等,以区分不同的原因

但是,这意味着从这个表中提取数据会得到非常分散的结果,我希望忽略这些偏移量来聚合数据,即,将具有一分钟偏移量的记录视为不存在偏移量

换句话说,当我遇到一个时间戳为08:59:00的记录时,我想拉一个时间戳为09:00:00的记录

我尝试了不同的方法,使用CASE/WHEN语句和datediff来确定是否应该在时间戳中添加一分钟,我没有开始工作,或者是循环,这没有产生预期的结果,我认为这与hh:mm:ss格式是一种非标准的日期/时间格式有关


任何提示/建议?

使用Informix 12.10FC8DE,我可以使用以下内容:

CREATE TABLE my_dlv_tm
(
    id INTEGER
    , tmstmp DATETIME HOUR TO SECOND
);

INSERT INTO my_dlv_tm VALUES (1, '09:00:00');
INSERT INTO my_dlv_tm VALUES (2, '08:59:00');
INSERT INTO my_dlv_tm VALUES (3, '09:01:00');
INSERT INTO my_dlv_tm VALUES (4, '00:00:00');
INSERT INTO my_dlv_tm VALUES (5, '23:59:00');
INSERT INTO my_dlv_tm VALUES (6, '00:01:00');
在示例表中,我使用以下语句:

SELECT
    id
    , tmstmp
    , ROUND(tmstmp::DATETIME YEAR TO SECOND, 'HH')::DATETIME HOUR TO SECOND AS rounded_tmstmp
FROM
    my_dlv_tm;


 id tmstmp   rounded_tmstmp

  1 09:00:00 09:00:00
  2 08:59:00 09:00:00
  3 09:01:00 09:00:00
  4 00:00:00 00:00:00
  5 23:59:00 00:00:00
  6 00:01:00 00:00:00

6 row(s) retrieved.
直接使用
DATETIME小时到秒
会产生以下错误:

1263: A field in a datetime or interval value is incorrect or an illegal operation
因此,我将
DATETIME HOUR TO SECOND
转换为
DATETIME YEAR TO SECOND
,使用
ROUND
函数,最后将结果转换回
DATETIME HOUR TO SECOND


我不确定它为什么需要强制转换,从我在上一次阅读的内容来看,我不明白
ROUND
DATETIME
参数需要一个日期组件。我分两步工作(TDQD的一种形式——测试驱动的查询设计)。一个主要问题是,将30分钟添加到DATETIME小时到秒的值(如
23:59:00
)会溢出DATETIME小时到秒的可接受值范围

步骤1:使用DATETIME年到秒 如果将表达式
EXTEND(EXTEND(dt+30单位分钟,一年到一小时,一年到一秒)
分阶段分解,可能会更简单,这就是它的发展过程:

dt + 30 UNITS MINUTE
这样每次都会增加30分钟,愉快地结束到第二天的早些时候

EXTEND(dt + 30 UNITS MINUTE, YEAR TO  HOUR
这将删除分钟和秒,截断值(这就是添加30分钟的原因)

这将恢复分和秒,但将其设置为零。双延伸操作至关重要。例如,尝试仅使用
扩展(dt+30单位分钟,小时到秒)
不会将答案的分和秒部分归零

步骤2:使用DATETIME小时到秒 这完全基于上一步,但利用了这样一个事实,即当您使用“年到日”组件将DATETIME HOUR扩展为秒值时,它们会采用与当前日期对应的值。因此:

+ CREATE TABLE round_time
(
    id SERIAL NOT NULL PRIMARY KEY,
    dt DATETIME HOUR TO SECOND NOT NULL
);
+ INSERT INTO round_time VALUES (0, '09:00:00');
+ INSERT INTO round_time VALUES (0, '08:59:00');
+ INSERT INTO round_time VALUES (0, '09:01:00');
+ INSERT INTO round_time VALUES (0, '00:00:00');
+ INSERT INTO round_time VALUES (0, '23:29:59');
+ INSERT INTO round_time VALUES (0, '23:30:00');
+ INSERT INTO round_time VALUES (0, '23:59:00');
+ INSERT INTO round_time VALUES (0, '00:01:00');
+ INSERT INTO round_time VALUES (0, '00:29:59');
+ INSERT INTO round_time VALUES (0, '00:30:00');
+ SELECT id,
       dt,
       EXTEND(dt, YEAR TO SECOND),
       EXTEND(EXTEND(EXTEND(dt, YEAR TO SECOND) + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND),
       EXTEND(EXTEND(EXTEND(dt, YEAR TO SECOND) + 30 UNITS MINUTE, YEAR TO HOUR), HOUR TO SECOND)
  FROM round_time
 ORDER BY dt;
SERIAL  DATETIME HOUR TO SECOND DATETIME YEAR TO SECOND DATETIME YEAR TO SECOND DATETIME HOUR TO SECOND
4       00:00:00        2017-12-16 00:00:00     2017-12-16 00:00:00     00:00:00
8       00:01:00        2017-12-16 00:01:00     2017-12-16 00:00:00     00:00:00
9       00:29:59        2017-12-16 00:29:59     2017-12-16 00:00:00     00:00:00
10      00:30:00        2017-12-16 00:30:00     2017-12-16 01:00:00     01:00:00
2       08:59:00        2017-12-16 08:59:00     2017-12-16 09:00:00     09:00:00
1       09:00:00        2017-12-16 09:00:00     2017-12-16 09:00:00     09:00:00
3       09:01:00        2017-12-16 09:01:00     2017-12-16 09:00:00     09:00:00
5       23:29:59        2017-12-16 23:29:59     2017-12-16 23:00:00     23:00:00
6       23:30:00        2017-12-16 23:30:00     2017-12-17 00:00:00     00:00:00
7       23:59:00        2017-12-16 23:59:00     2017-12-17 00:00:00     00:00:00
最后一列似乎是你想要的答案。显然,如果表中已经有一个合适的
DATE
列,则可以使用该列,尤其是如果您希望该日期成为分析的一部分。然后,您将在步骤1 SQL上使用一些变体来生成适当的结果


与所有日期/时间计算(至少在Informix中)一样,表达式冗长。

欢迎使用堆栈溢出。请阅读,然后。研究、尝试、添加代码并指出问题。棘手的问题时间:23:30:00和23:59:59的时间应该映射到-00:00:00、24:00:00或其他值?如果输入在23:30:00-23:59:59范围内,是否有一个日期组件应该增加?非常感谢您的想法。我碰巧知道没有23:59:00的事件发生,但是,如果有,我希望以同样的方式对待它们,也就是说,它们实际上是在下一个小时的最高峰开始的。我猜答案是00:00:00。幸运的是,没有要处理的日期组件,或者在这种情况下必须增加。数据库仅包含hh:mm:ss格式的时间戳。它们实际上是交付槽窗口开始的指示,交付日期在单独的列中。
EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO  HOUR), YEAR TO SECOND)
+ CREATE TABLE round_time
(
    id SERIAL NOT NULL PRIMARY KEY,
    dt DATETIME HOUR TO SECOND NOT NULL
);
+ INSERT INTO round_time VALUES (0, '09:00:00');
+ INSERT INTO round_time VALUES (0, '08:59:00');
+ INSERT INTO round_time VALUES (0, '09:01:00');
+ INSERT INTO round_time VALUES (0, '00:00:00');
+ INSERT INTO round_time VALUES (0, '23:29:59');
+ INSERT INTO round_time VALUES (0, '23:30:00');
+ INSERT INTO round_time VALUES (0, '23:59:00');
+ INSERT INTO round_time VALUES (0, '00:01:00');
+ INSERT INTO round_time VALUES (0, '00:29:59');
+ INSERT INTO round_time VALUES (0, '00:30:00');
+ SELECT id,
       dt,
       EXTEND(dt, YEAR TO SECOND),
       EXTEND(EXTEND(EXTEND(dt, YEAR TO SECOND) + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND),
       EXTEND(EXTEND(EXTEND(dt, YEAR TO SECOND) + 30 UNITS MINUTE, YEAR TO HOUR), HOUR TO SECOND)
  FROM round_time
 ORDER BY dt;
SERIAL  DATETIME HOUR TO SECOND DATETIME YEAR TO SECOND DATETIME YEAR TO SECOND DATETIME HOUR TO SECOND
4       00:00:00        2017-12-16 00:00:00     2017-12-16 00:00:00     00:00:00
8       00:01:00        2017-12-16 00:01:00     2017-12-16 00:00:00     00:00:00
9       00:29:59        2017-12-16 00:29:59     2017-12-16 00:00:00     00:00:00
10      00:30:00        2017-12-16 00:30:00     2017-12-16 01:00:00     01:00:00
2       08:59:00        2017-12-16 08:59:00     2017-12-16 09:00:00     09:00:00
1       09:00:00        2017-12-16 09:00:00     2017-12-16 09:00:00     09:00:00
3       09:01:00        2017-12-16 09:01:00     2017-12-16 09:00:00     09:00:00
5       23:29:59        2017-12-16 23:29:59     2017-12-16 23:00:00     23:00:00
6       23:30:00        2017-12-16 23:30:00     2017-12-17 00:00:00     00:00:00
7       23:59:00        2017-12-16 23:59:00     2017-12-17 00:00:00     00:00:00