【发布时间】:2011-06-16 15:32:22
【问题描述】:
如何确定 INTERVAL 值的最大分辨率?例如:
-
INTERVAL '100 days and 3 seconds'=> 一天 -
TIME '20:05' - TIME '12:01:01'=> 小时 -
AGE(NOW(), NOW() - INTERVAL '1 MONTH')=> 月
【问题讨论】:
标签: sql postgresql intervals
如何确定 INTERVAL 值的最大分辨率?例如:
INTERVAL '100 days and 3 seconds' => 一天TIME '20:05' - TIME '12:01:01' => 小时AGE(NOW(), NOW() - INTERVAL '1 MONTH') => 月【问题讨论】:
标签: sql postgresql intervals
这个问题不是 100% 清楚的,所以答案可能是也可能不是你正在寻找的,但是......
有一个justify_interval() 函数,您可能想研究一下。
test=# select justify_interval(INTERVAL '100 days 3 seconds');
justify_interval
-------------------------
3 mons 10 days 00:00:03
(1 row)
test=# select justify_interval(TIME '20:05' - TIME '12:01:01');
justify_interval
------------------
08:03:59
(1 row)
test=# select justify_interval(AGE(NOW(), NOW() - INTERVAL '1 MONTH'));
justify_interval
------------------
1 mon
(1 row)
在那里提取年份、月份、日期等,直到你得出一个非零的答案:
test=# select extract('mon' from interval '3 mons 10 days 00:00:03');
date_part
-----------
3
关于 cmets 的另一个问题:
create function max_res(interval) returns interval as $$
select case
when extract('year' from justify_interval($1)) > 0 or
extract('mon' from justify_interval($1)) > 0 or
extract('day' from justify_interval($1)) > 0
then '1 day'
when extract('hour' from justify_interval($1)) > 0
then '1 hour'
when ...
end;
$$ language sql immutable strict;
【讨论】:
INTERVAL '30 HOUR' 大于 INTERVAL '1 DAY',但比例分别是 HOUR 和 DAY。两者都不会转换为秒。
INTERVAL 是 12 个字节,是一个包含月、日和微秒的结构,范围为 +/- 178000000 年。由于它存储此信息的方式,它始终具有 178000000 年的固定最大大小。
请注意您对“一个月”的理解,因为儒略月与 hour 或 minute 不同(例如,二月份有多少天?或者如何year 中有很多天?实际上并不总是 30 或 365,PostgreSQL 会正确更新。根据 IRC 上的一次有趣对话,将 1 month::INTERVAL 添加到 1 月 30 日将导致 2 月的最后一天因为它增加了struct tm 的tm_mon 成员(在这种情况下,回滚到之前的有效日期)。
啊哈!我现在得到了这个问题(或者至少我是这么认为的)。您正在寻找给定INTERVAL 的最大“非零整数单元”。
PostgreSQL 没有返回该信息的内置函数。我认为您将不得不链接条件和返回类型。一些例子PL代码:
t := EXTRACT(EPOCH FROM my_time_input);
IF t >= 31104000 THEN
RETURN 'year';
ELSIF t >= 2592000 THEN
RETURN 'month';
ELSIF t >= 604800 THEN
RETURN 'week';
ELSIF t >= 86400 THEN
RETURN 'day';
ELSIF t >= 3600 THEN
RETURN 'hour';
ELSIF t >= 60 THEN
RETURN 'minute'
ELSIF t > 1 THEN
RETURN 'seconds';
ELSIF t == 1 THEN
RETURN 'second';
ELSE
RETURN resolve_largest_sub_second_unit(my_time);
END IF;
【讨论】:
INTERVAL 的最大非小数单位,对吗?人力资源管理系统。用建议编辑问题。