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

问题描述 投票:2回答:2

我有一个数据库表,其中有一个名为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格式有关,是非标准的日期/时间格式。

有什么提示/建议吗?

sql time informix
2个回答
2
投票

这是另一种接近它的方法。我分两个步骤(TDQD的形式 - 测试驱动的查询设计)。一个主要问题是,在DATETIME HOUR TO SECOND值(如23:59:00)中添加30分钟会溢出DATETIME HOUR TO SECOND的可接受值范围。

Step 1: Using 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)不会将答案的分钟和秒组成零。

Step 2: Using DATETIME 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中),表达式是罗嗦的。


2
投票

使用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读到的我不明白DATETIMEROUND论证需要一个日期组件。

© www.soinside.com 2019 - 2024. All rights reserved.