我有一个数据库表,其中有一个名为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确定是否应该在时间戳上添加一分钟,我没有工作,或者ROUND,它没有产生我认为的预期结果与hh:mm:ss格式有关,是非标准的日期/时间格式。
有什么提示/建议吗?
这是另一种接近它的方法。我分两个步骤(TDQD的形式 - 测试驱动的查询设计)。一个主要问题是,在DATETIME HOUR TO SECOND值(如23:59:00
)中添加30分钟会溢出DATETIME HOUR 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)
不会将答案的分钟和秒组成零。
这是基于前一步骤,但利用了这样的事实:当您使用YEAR到DAY组件延长DATETIME HOUR 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
最后一栏似乎可能是你想要的答案。显然,如果表中已有合适的DATE
列,则可以使用它,尤其是如果您希望日期成为分析的一部分。然后,您将使用Step 1 SQL的一些变体来生成适当的结果。
与所有日期/时间计算一样(至少在Informix中),表达式是罗嗦的。
使用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 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读到的我不明白DATETIME
的ROUND
论证需要一个日期组件。