在 Informix 中将时间戳舍入到整整一个小时 SQL
Round timestamps up to a whole hour in Informix SQL
我有一个数据库 table,它有一个名为 dlv_tm 的列,其中包含格式为 hh:mm:ss
的时间戳
大多数时间戳都是整小时,例如09:00:00、11:00:00 等,但有些是故意偏移一分钟,例如08:59:00, 10:59:00, 等等,以区分它们。
然而,这意味着从这个 table 中提取数据会得到非常分散的结果,我想汇总忽略这些偏移量的数据,即处理具有该一分钟偏移量的记录,就好像偏移量是在那里。
换句话说,当遇到时间戳为08:59:00的记录时,我想拉取时间戳为09:00:00的记录。
我尝试了不同的方法,使用 CASE/WHEN 语句和 datediff 来确定我是否应该在时间戳中添加一分钟,我没有开始工作,或者 ROUND,这没有产生预期的结果,我认为这与 hh:mm:ss 格式是非标准 date/time 格式有关。
任何tips/suggestions?
使用 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');
在示例table中我使用了以下语句:
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 HOUR TO SECOND
会产生以下错误:
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
。
我不确定为什么它需要强制转换,根据我在 IBM® Informix® 12.10 ROUND Function 阅读的内容,我不明白 ROUND
的 DATETIME
参数需要一个日期组件。
这是处理它的另一种方法。我分两步工作(TDQD 的一种形式——测试驱动的查询设计)。一个主要问题是,将 30 分钟添加到 DATETIME HOUR TO SECOND 值(例如 23:59:00
)会溢出 DATETIME HOUR TO SECOND 的 acceptable 值的范围。
第 1 步:使用 DATETIME YEAR TO SECOND
+ CREATE TABLE round_datetime
(
id SERIAL NOT NULL PRIMARY KEY,
dt DATETIME YEAR TO SECOND NOT NULL
);
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 09:00:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 08:59:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 09:01:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:00:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:29:59');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:30:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:59:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:01:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:29:59');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:30:00');
+ SELECT id,
dt,
EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
FROM round_datetime
ORDER BY dt;
SERIAL DATETIME YEAR TO SECOND DATETIME YEAR TO SECOND
4 2017-12-18 00:00:00 2017-12-18 00:00:00
8 2017-12-18 00:01:00 2017-12-18 00:00:00
9 2017-12-18 00:29:59 2017-12-18 00:00:00
10 2017-12-18 00:30:00 2017-12-18 01:00:00
2 2017-12-18 08:59:00 2017-12-18 09:00:00
1 2017-12-18 09:00:00 2017-12-18 09:00:00
3 2017-12-18 09:01:00 2017-12-18 09:00:00
5 2017-12-18 23:29:59 2017-12-18 23:00:00
6 2017-12-18 23:30:00 2017-12-19 00:00:00
7 2017-12-18 23:59:00 2017-12-19 00:00:00
表达式EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
如果分阶段分解可能会更简单,这就是它的发展方式:
dt + 30 UNITS MINUTE
每次增加 30 分钟,愉快地结束到第二天的早些时候。
EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR
这将删除 MINUTES 和 SECONDS,截断值(这就是添加 30 分钟的原因)。
EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
这将恢复 MINUTES 和 SECONDS,但将它们设置为零。双重 EXTEND 操作至关重要。例如,尝试仅使用 EXTEND(dt + 30 UNITS MINUTE, HOUR TO SECOND)
不会将答案的分钟和秒部分归零。
第 2 步:使用 DATETIME HOUR TO SECOND
这与上一步非常相似,但利用了以下事实:当您将带有 YEAR 的 DATETIME HOUR TO SECOND 值扩展到 DAY 组件时,它们会采用与当前日期对应的值。因此:
+ 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
最后一栏似乎是您想要的答案。显然,如果 table 中已经有一个 suitable DATE
列,则可以改用它,特别是如果您希望日期成为分析的一部分。然后,您将在步骤 1 SQL 上使用一些变体来产生适当的结果。
与所有 date/time 计算一样(至少在 Informix 中),表达式很冗长。
我有一个数据库 table,它有一个名为 dlv_tm 的列,其中包含格式为 hh:mm:ss
的时间戳大多数时间戳都是整小时,例如09:00:00、11:00:00 等,但有些是故意偏移一分钟,例如08:59:00, 10:59:00, 等等,以区分它们。
然而,这意味着从这个 table 中提取数据会得到非常分散的结果,我想汇总忽略这些偏移量的数据,即处理具有该一分钟偏移量的记录,就好像偏移量是在那里。
换句话说,当遇到时间戳为08:59:00的记录时,我想拉取时间戳为09:00:00的记录。
我尝试了不同的方法,使用 CASE/WHEN 语句和 datediff 来确定我是否应该在时间戳中添加一分钟,我没有开始工作,或者 ROUND,这没有产生预期的结果,我认为这与 hh:mm:ss 格式是非标准 date/time 格式有关。
任何tips/suggestions?
使用 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');
在示例table中我使用了以下语句:
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 HOUR TO SECOND
会产生以下错误:
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
。
我不确定为什么它需要强制转换,根据我在 IBM® Informix® 12.10 ROUND Function 阅读的内容,我不明白 ROUND
的 DATETIME
参数需要一个日期组件。
这是处理它的另一种方法。我分两步工作(TDQD 的一种形式——测试驱动的查询设计)。一个主要问题是,将 30 分钟添加到 DATETIME HOUR TO SECOND 值(例如 23:59:00
)会溢出 DATETIME HOUR TO SECOND 的 acceptable 值的范围。
第 1 步:使用 DATETIME YEAR TO SECOND
+ CREATE TABLE round_datetime
(
id SERIAL NOT NULL PRIMARY KEY,
dt DATETIME YEAR TO SECOND NOT NULL
);
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 09:00:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 08:59:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 09:01:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:00:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:29:59');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:30:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 23:59:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:01:00');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:29:59');
+ INSERT INTO round_datetime VALUES (0, '2017-12-18 00:30:00');
+ SELECT id,
dt,
EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
FROM round_datetime
ORDER BY dt;
SERIAL DATETIME YEAR TO SECOND DATETIME YEAR TO SECOND
4 2017-12-18 00:00:00 2017-12-18 00:00:00
8 2017-12-18 00:01:00 2017-12-18 00:00:00
9 2017-12-18 00:29:59 2017-12-18 00:00:00
10 2017-12-18 00:30:00 2017-12-18 01:00:00
2 2017-12-18 08:59:00 2017-12-18 09:00:00
1 2017-12-18 09:00:00 2017-12-18 09:00:00
3 2017-12-18 09:01:00 2017-12-18 09:00:00
5 2017-12-18 23:29:59 2017-12-18 23:00:00
6 2017-12-18 23:30:00 2017-12-19 00:00:00
7 2017-12-18 23:59:00 2017-12-19 00:00:00
表达式EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
如果分阶段分解可能会更简单,这就是它的发展方式:
dt + 30 UNITS MINUTE
每次增加 30 分钟,愉快地结束到第二天的早些时候。
EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR
这将删除 MINUTES 和 SECONDS,截断值(这就是添加 30 分钟的原因)。
EXTEND(EXTEND(dt + 30 UNITS MINUTE, YEAR TO HOUR), YEAR TO SECOND)
这将恢复 MINUTES 和 SECONDS,但将它们设置为零。双重 EXTEND 操作至关重要。例如,尝试仅使用 EXTEND(dt + 30 UNITS MINUTE, HOUR TO SECOND)
不会将答案的分钟和秒部分归零。
第 2 步:使用 DATETIME HOUR TO SECOND
这与上一步非常相似,但利用了以下事实:当您将带有 YEAR 的 DATETIME HOUR TO SECOND 值扩展到 DAY 组件时,它们会采用与当前日期对应的值。因此:
+ 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
最后一栏似乎是您想要的答案。显然,如果 table 中已经有一个 suitable DATE
列,则可以改用它,特别是如果您希望日期成为分析的一部分。然后,您将在步骤 1 SQL 上使用一些变体来产生适当的结果。
与所有 date/time 计算一样(至少在 Informix 中),表达式很冗长。