TIMESTAMPDIFF alias in postgresql - postgresql

I recently switched to using postgreSQL and I am having same difficulties finding an alternative for timestampiff
My original query was something like
select a.column_a, a.column_b, TIMESTAMPDIFF(SQL_TSI_MINUTE, a.TIME_START, now()) AS "Time_diff"
from table as a
where
...
I can do just ( now() - a.TIME_START) but i want to show the result in minutes. Is there any better alternatives in postgresql to do the subtraction from now and show the result just as minutes ?

now() - a.TIME_START returns an interval which can be converted to seconds using extract() and those can be converted to minutes:
extract(epoch from now() - a.time_start) / 60 as diff_minutes
If you don't need it as a number, another option is to simply format the interval to show minutes and seconds
to_char(now() - a.time_start, 'mi:ss')
Note that this will hide the information if the interval was bigger than 60 minutes (or bigger than a day). If that can happen as well, maybe you want to use 'dd hh24:mi:ss' as a format mask instead

Related

Subract Additional Time from $__timeFilter

I want to subract additional time in $__timeFilter in grafana. Like if I have selected Last 7 days, I want to run 2 queries which do a comparison like one query gives me avg cpu utilization for last 7 days and another one gives me avg cpu utilzation for now() - 14d to now() - 7d. And this is dynamic. I can get for 6hrs, 2days or anything selected.
My database is TimescaleDB and grafana version in 8.3.5
Edit
Query is
select avg(cpu) from cpu_utilization where $__timeFilter(timestamp)
Whatever is selected in the time filter in grafana, the query is manipulated accordingly
Now with grafana understands this query becomes as following. if I select last 24hrs
select avg(cpu) from cpu_utilization where timestamp BETWEEN '2022-09-07 05:32:10' and '2022-09-08 05:32:10'
This is normal behaviour. Now I wanted that if I select last 24hrs, this query to behave as it is but an additional query becomes
select avg(cpu) from cpu_utilization where timestamp BETWEEN '2022-09-06 05:32:10' and '2022-09-07 05:32:10'
(I just don't want it for last 24hrs, but any relative time period selected in the filter)
Answer : https://stackoverflow.com/a/73658919/14817486
You can use the global variables $__to and $__from.
For example, ${__from:date:seconds} will give you a timestamp in seconds. You can then subtract 7 days (= 604800 seconds) from it and use it in your query's WHERE clause. Depending on your SQL dialect, that might be by using TIMESTAMP(), TO_TIMESTAMP() or something similar. So it would look similar to this:
[...] WHERE timestamp BETWEEN TO_TIMESTAMP(${__from:date:seconds}-604800) AND TO_TIMESTAMP(${__to:date:seconds}-604800) [...]
Interesting question! If I understood correctly, you could use the timestamp column as the reference as the grafana is already filtering by this to the comparison query. So you can get the min(timestamp) and max(timestamp) to know the limits of your period and then build something from it.
Like min(timestamp) - INTERVAL '7 days' would give you the start of the previous range, and max(timestamp) - INTERVAL '7 days' would offer the final scope.

find the differences in minutes between two dates having timestamp?

I am using Postgres and looking to find the differences between two dates having timestamp, how can we get the values in minutes?
SELECT DATE_PART('sec', '2021-02-03 08:14:52'::timestamp) - DATE_PART('sec', '2021-02-03 08:17:16'::timestamp);
demo:db<>fiddle
The difference of two timestamps yields a type interval. You can use EXTRACT(epoch from ...) on intervals to receive the intervals in seconds:
SELECT
extract(epoch from
'2021-02-03 08:17:16'::timestamp - '2021-02-03 08:14:52'::timestamp
) / 60
Divide the result by 60 gives you the minutes.

Difference between two timestamps as timestamp across multiple days

I have two timestamps and I would like to have a result with the difference between them. I found a similar question asked here but I have noticed that:
select
to_char(column1::timestamp - column2::timestamp, 'HH:MS:SS')
from
table
Gives me an incorrect return if these timestamps cross multiple days. I know that I can use EPOCH to work out the number of hours/days/minutes/seconds etc but my use case requires the result as a timestamp (or a string...anything not an interval!).
In the case of multiple days I would like to continue counting the hours, even if it should go past 24. This would allow results like:
36:55:01
I'd use the built-in date_part function (as previously described in an older thread: How to convert an interval like "1 day 01:30:00" into "25:30:00"?) but finally cast the result to the type you desire:
SELECT
from_date,
to_date,
to_date - from_date as date_diff_interval,
(date_part('epoch', to_date - from_date) * INTERVAL '1 second')::text as date_diff_text
from (
(select
'2018-01-01 04:03:06'::timestamp as from_date,
'2018-01-02 16:58:07'::timestamp as to_date)
) as dates;
This results in the following:
I'm currently unaware of any way to convert this interval into a timestamp and also not sure whether there is a use for it. You're still dealing with an interval and you'd need a point of reference in time to transform that interval into an actual timestamp.

postgresql: generate interval count of hours between two timestamps

I am using postgres 8.3.12 and novice.
I have a column formatted as follows: '29/04/2013 at 09:27:51 PM (or AM)'
I am doing the following to set them to a timestamp:
case when <criteria> to_timestamp(time, 'MM/DD/YYYY at HH:MI:SS AM') as start
case when <criteria> to_timestamp(time, 'MM/DD/YYYY at HH:MI:SS AM') as end
My goal is to calculate the hours between two time stamps.
I looked at http://www.postgresql.org/docs/current/static/functions-datetime.html
After I set them to timestamps, is it simply
end - start as difference;
Assuming you have two columns named timea and timeb, the following will return you the number of hours between them in PostgreSQL:
SELECT EXTRACT(EPOCH FROM timea - timeb) / 3600 AS hours FROM ...;
It might also be useful to note that:
EXTRACT(EPOCH FROM timea - timeb)
Also, timea and timeb don't need to be columns - you can use whatever expressions you want here, as long as they are timestamps.
Will return to you the number of seconds between the two timestamps - this can be useful to compute the number of minutes, hours, days, etc. - whatever you like. Hours, in particular, contain 3600 seconds, so you simply divide by 3600 to get the number of hours.
The EXTRACT function can do all kinds of powerful things for you. I'd suggest looking at the documentation for it here.

How to convert an interval like "1 day 01:30:00" into "25:30:00"?

I need to add some intervals and use the result in Excel.
Since
sum(time.endtime-time.starttime)
returns the interval as "1 day 01:30:00" and this format breaks my Excel sheet, I thought it'd be nice to have the output like "25:30:00" but found no way to do it in the PostgreSQL documentation.
Can anyone here help me out?
Since there is not an exact solution for the topic:
=> SELECT date_part('epoch', INTERVAL '1 day 01:30:00') * INTERVAL '1 second' hours;
hours
-----------
25:30:00
(1 row)
Source: Documentation
The only thing I can come with (beside parsing the number of days and adding 24 to the hours every time) is :
mat=> select date_part('epoch', '01 day 1:30:00'::interval);
date_part
-----------
91800
(1 row)
It will give you the number of seconds, which may be ok for excel.
You could use EXTRACT to convert the interval into seconds.
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
Result: 442800
Then you would need to do your own maths (or let Excel do it).
Note that '1 day' is not necessarily equivalent to '24 hours' - PostgreSQL handles things like an interval that spans a DST transition.
If you wanted postgres to handle the HH:MM:SS formatting for you, take the difference in epoch seconds and convert it to an interval scaled in seconds:
SELECT SUM(EXTRACT(EPOCH FROM time.endtime) - EXTRACT(EPOCH FROM time.starttime))
* INTERVAL '1 SECOND' AS hhmmss
In standard SQL, you want to represent the type as INTERVAL HOUR TO SECOND, but you have a value of type INTERVAL DAY TO SECOND. Can you not use a CAST to get to your required result? In Informix, the notation would be either of:
SUM(time.endtime - time.starttime)::INTERVAL HOUR(3) TO SECOND
CAST(SUM(time.endtime - time.starttime) AS INTERVAL HOUR(3) TO SECOND)
The former is, AFAIK, Informix-specific notation (or, at least, not standard); the latter is, I believe, SQL standard notation.
It can be done, but I believe that the only way is through the following monstrosity (assuming your time interval column name is "ti"):
select
to_char(floor(extract(epoch from ti)/3600),'FM00')
|| ':' || to_char(floor(cast(extract(epoch from ti) as integer) % 3600 / 60), 'FM00')
|| ':' || to_char(cast(extract(epoch from ti) as integer) % 60,'FM00')
as hourstamp
from whatever;
See? I told you it was horrible :)
It would have been nice to think that
select to_char(ti,'HH24:MI:SS') as hourstamp from t
would worked, but alas, the HH24 format doesn't "absorb" the overflow beyond 24. The above comes (reconstructed from memory) from some code I once wrote. To avoid offending those of delicate constitution, I encapsulated the above shenanigans in a view...