如何获得间隔的绝对值

moo*_*eep 12 postgresql

请考虑以下声明:

select interval '-1 hours'
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何获得间隔的绝对值,即如果为负则切换或移除符号.我想到的唯一一件事是:

select abs(extract(epoch from interval '-1 hours'))
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*dez 12

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

SELECT greatest(-'1 hour'::interval, '1 hour'::interval);
Run Code Online (Sandbox Code Playgroud)


Dan*_*ité 10

在 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;
Run Code Online (Sandbox Code Playgroud)

简单的 SQL 函数通常在查询执行期间内联,因此性能应该与在查询中包含表达式相当。

例子:

#= select abs(interval '-2 days +3 minutes');
       abs        
------------------
 2 days -00:03:00


# select abs(now()-clock_timestamp());
       abs       
-----------------
 00:00:00.000146
Run Code Online (Sandbox Code Playgroud)


小智 6

一个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)
Run Code Online (Sandbox Code Playgroud)

产生:

     i     |  abs_i
-----------+----------
 -02:00:00 | 02:00:00
 00:02:00  | 00:02:00