【发布时间】:2012-08-17 11:20:52
【问题描述】:
考虑以下语句:
select interval '-1 hours'
我不知道如何获得间隔的绝对值,即如果为负则切换或删除符号。我唯一想到的就是以下几点:
select abs(extract(epoch from interval '-1 hours'))
但是不知道有没有更优雅的方式(保留区间类型的方式)?
【问题讨论】:
标签: postgresql
考虑以下语句:
select interval '-1 hours'
我不知道如何获得间隔的绝对值,即如果为负则切换或删除符号。我唯一想到的就是以下几点:
select abs(extract(epoch from interval '-1 hours'))
但是不知道有没有更优雅的方式(保留区间类型的方式)?
【问题讨论】:
标签: postgresql
您可以找到 i 和 -i 之间的最大值。例如:
SELECT greatest(-'1 hour'::interval, '1 hour'::interval);
【讨论】:
在 pgsql-general 邮件列表:Absolute value of intervals 上讨论了为什么 PostgreSQL 没有提供内置的 abs(interval) 函数。
简而言之,在考虑区间类型的组件化性质时,对于在某些情况下应该做什么并没有达成共识。
但是任何人都可以创建他们的函数来实现他们自己关于它应该计算什么的想法,例如,基于来自LisMorski's answer 的表达式:
CREATE FUNCTION abs(interval) RETURNS interval AS
$$ select case when ($1<interval '0') then -$1 else $1 end; $$
LANGUAGE sql immutable;
简单的 SQL 函数通常在查询执行期间内联,因此性能应该与在查询中包含表达式相当。
例子:
#= select abs(interval '-2 days +3 minutes');
abs
------------------
2 days -00:03:00
# select abs(now()-clock_timestamp());
abs
-----------------
00:00:00.000146
【讨论】:
CASE 表达式看起来更不言自明。示例:
SELECT
i,
(CASE WHEN (i < INTERVAL '0') THEN (-i) ELSE i END) AS abs_i
FROM
(VALUES
(INTERVAL '-2 h'),
(INTERVAL '2 m')
) AS foo (i)
产生:
我 | abs_i ----------+---------- -02:00:00 | 02:00:00 00:02:00 | 00:02:00
【讨论】:
它并不比你的更优雅,但它返回一个区间类型
select interval '-1 hours'*sign(extract(epoch from interval '-1 hours'))
【讨论】: