在Informix SQL中将时间戳舍入到一整小时
我有一个数据库表,它有一个名为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 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
任何提示/建议?使用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