Consider the following statement:
select interval '-1 hours'
I couldn't figure out how to get the absolute value of an interval, i.e. to toggle or remove the sign if negative. The only thing that came to my mind is the following:
select abs(extract(epoch from interval '-1 hours'))
But I wonder if there is a more elegant way (a way that preserves the interval type)?
When x < 0 both absolute values contain negative numbers that become positive when we take the absolute value. We can do this algebraically by replacing the absolute value sign with a bracket and multiplying by −1. On the interval 0 x < 2 , only the value in the first absolute value term is negative.
The absolute value of a number x is generally represented as | x | = a, which implies that, x = + a and -a. We say that the absolute value of a given number is the positive version of that number. For example, the absolute value of negative 5 is positive 5, and this can be written as: | − 5 | = 5.
The most common way to represent the absolute value of a number or expression is to surround it with the absolute value symbol: two vertical straight lines. |6| = 6 means “the absolute value of 6 is 6.” |–6| = 6 means “the absolute value of –6 is 6.” |–2 – x| means “the absolute value of the expression –2 minus x.”
You can find the greatest value between i and -i. For example:
SELECT greatest(-'1 hour'::interval, '1 hour'::interval);
There's a discussion on the pgsql-general mailing-list: Absolute value of intervals on why a built-in abs(interval)
function is not provided with PostgreSQL.
In short, there's no consensus about what it should do in some cases, when considering the componentized nature of the interval type.
But anyone can create their function implementing their own idea about what it should compute, for instance, building on the expression from LisMorski's answer:
CREATE FUNCTION abs(interval) RETURNS interval AS $$ select case when ($1<interval '0') then -$1 else $1 end; $$ LANGUAGE sql immutable;
Simple SQL functions are generally inlined during query execution, so the performance should be comparable to having the expression inside the query.
Example:
#= select abs(interval '-2 days +3 minutes'); abs ------------------ 2 days -00:03:00 # select abs(now()-clock_timestamp()); abs ----------------- 00:00:00.000146
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With