21

考虑以下语句:

select interval '-1 hours'

我不知道如何获得间隔的绝对值,即如果为负则切换或删除符号。我唯一想到的是以下内容:

select abs(extract(epoch from interval '-1 hours'))

但我想知道是否有更优雅的方式(一种保留区间类型的方式)?

4

4 回答 4

17

您可以找到 i 和 -i 之间的最大值。例如:

SELECT greatest(-'1 hour'::interval, '1 hour'::interval);
于 2014-04-30T01:47:32.170 回答
11

关于 pgsql-general 邮件列表的讨论:关于为什么PostgreSQL 不提供内置函数的间隔绝对值。 简而言之,在考虑区间类型的组件化性质时,在某些情况下应该做什么并没有达成共识。abs(interval)

但是任何人都可以创建他们的函数来实现他们自己关于它应该计算什么的想法,例如,基于LisMorski 的答案中的表达式:

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
于 2017-06-27T19:01:37.990 回答
10

表达式看起来更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
于 2012-08-17T11:44:52.417 回答
3

它并不比你的更优雅,但它返回一个区间类型

select interval '-1 hours'*sign(extract(epoch from interval '-1 hours'))  
于 2012-08-17T11:46:24.783 回答