AS400/DB2 - 将基于整数的日期和时间转换为时间戳?
AS400/DB2 - Converting integer based dates and times to a timestamp?
我有 4 个用户输入:startDate
、endDate
、startTime
、endTime
。
数据库中的日期和时间设置与我以前使用的任何设置都不同。日期是自 1900 年 12 月 31 日以来的天数。因此是一个整数。例如,2015 年 10 月 16 日,将表示为 41927。
时间采用 ISO 格式 - 没有小数点,因此也是整数。所以 08:00:00 将是 80000。19:00:00 将是 190000。它基本上是 hhmmss - 但有时你只有一个 h。
我正在尝试将日期和时间过滤到范围内。有一天,我只是在看时间,这很好用:
SELECT * FROM database WHERE day = 41927 AND time > startTime and time < endTime
如果您严格查看天数,它也有效:
SELECT * FROM database WHERE day > startDate AND day < endDate
当您需要两次查找两个日期之间的项目时就会出现问题,因为它会每天过滤掉这两个时间之间的所有内容。我知道有一种方法可以创建时间戳,但我正在努力使用两个整数将其放在查询中。
我有什么样的选择来解决这个问题?
您可以通过简单的算术来使用它:
select date('1900-12-31') + col days
不过,我怀疑真正的开始日期是1899-12-31。那是 Excel 使用的日期(所以第 1 天是 1900-01-01)。
编辑:
糟糕,漏掉了秒数。一种方法是:
select timestamp(date('1900-12-31') + coldays days) +
(floor(coltime / 10000) * 60*60 +
mod(floor(coltime / 100)) * 60
mod(coltime, 100)
) seconds
当您有一个可行的答案(来自您的评论)时...
select * from mytable
where CURRENT_TIMESTAMP
< timestamp(date('1900-12-31') + coldays days)
+ (floor(coltime / 10000) * 60*60
+ mod(floor(coltime / 100),100) * 60 mod(coltime, 100) )
您可能会发现它的性能不是很好,因为 WHERE
子句中列上的函数使用限制了标准索引的可用性。充其量,您将获得完整的索引扫描,而更糟糕的是,您将获得完整的 table 扫描。
两个选项
1) OS最近的一个版本(v6.1及更高版本)可以创建派生索引。
create index mytsidx on mytable
(timestamp(date('1900-12-31') + coldays days)
+ (floor(coltime / 10000) * 60*60
+ mod(floor(coltime / 100),100) * 60 mod(coltime, 100) )
seconds )
2) 在旧版本中,您需要将传入的时间戳转换成多个部分并进行比较:
select * from mytable
where (strdays < coldays
or strdays = coldays and strtime <= coltime)
and (enddays > coldays
or enddays = coldays and endtime >= coltime)
如果您选择选项 1,我建议您创建一个 UDF 来处理转换。
create index mytsidx on mytable (CONVERT_TO_TS(coldays,coltime));
select * from mytable
where CONVERT_TO_TS(coldays,coltime)
between start_ts and end_ts;
我有 4 个用户输入:startDate
、endDate
、startTime
、endTime
。
数据库中的日期和时间设置与我以前使用的任何设置都不同。日期是自 1900 年 12 月 31 日以来的天数。因此是一个整数。例如,2015 年 10 月 16 日,将表示为 41927。
时间采用 ISO 格式 - 没有小数点,因此也是整数。所以 08:00:00 将是 80000。19:00:00 将是 190000。它基本上是 hhmmss - 但有时你只有一个 h。
我正在尝试将日期和时间过滤到范围内。有一天,我只是在看时间,这很好用:
SELECT * FROM database WHERE day = 41927 AND time > startTime and time < endTime
如果您严格查看天数,它也有效:
SELECT * FROM database WHERE day > startDate AND day < endDate
当您需要两次查找两个日期之间的项目时就会出现问题,因为它会每天过滤掉这两个时间之间的所有内容。我知道有一种方法可以创建时间戳,但我正在努力使用两个整数将其放在查询中。
我有什么样的选择来解决这个问题?
您可以通过简单的算术来使用它:
select date('1900-12-31') + col days
不过,我怀疑真正的开始日期是1899-12-31。那是 Excel 使用的日期(所以第 1 天是 1900-01-01)。
编辑:
糟糕,漏掉了秒数。一种方法是:
select timestamp(date('1900-12-31') + coldays days) +
(floor(coltime / 10000) * 60*60 +
mod(floor(coltime / 100)) * 60
mod(coltime, 100)
) seconds
当您有一个可行的答案(来自您的评论)时...
select * from mytable
where CURRENT_TIMESTAMP
< timestamp(date('1900-12-31') + coldays days)
+ (floor(coltime / 10000) * 60*60
+ mod(floor(coltime / 100),100) * 60 mod(coltime, 100) )
您可能会发现它的性能不是很好,因为 WHERE
子句中列上的函数使用限制了标准索引的可用性。充其量,您将获得完整的索引扫描,而更糟糕的是,您将获得完整的 table 扫描。
两个选项
1) OS最近的一个版本(v6.1及更高版本)可以创建派生索引。
create index mytsidx on mytable
(timestamp(date('1900-12-31') + coldays days)
+ (floor(coltime / 10000) * 60*60
+ mod(floor(coltime / 100),100) * 60 mod(coltime, 100) )
seconds )
2) 在旧版本中,您需要将传入的时间戳转换成多个部分并进行比较:
select * from mytable
where (strdays < coldays
or strdays = coldays and strtime <= coltime)
and (enddays > coldays
or enddays = coldays and endtime >= coltime)
如果您选择选项 1,我建议您创建一个 UDF 来处理转换。
create index mytsidx on mytable (CONVERT_TO_TS(coldays,coltime));
select * from mytable
where CONVERT_TO_TS(coldays,coltime)
between start_ts and end_ts;