Returning 24+ hours in PostgreSQL query - postgresql

Alright... I have here a query that calculates a server uptime and sometimes this uptime goes over 24 hours. I use basically
select start, end, start-end as real_uptime from uptime
start and end being timestamp with timezone fields
Also, I have a stored function that sums all the real_uptime for a period and returns them...
However, I dumped the values start and end and put them into a spreadsheet and, doing the calculations there, the results had gone differently from what the stored function processed (the stored function returned lower values). I think that he ignores results for real_uptime bigger than one day. Postgresql shows them as x days hh:mm:ss... And I want them as hh:mm:ss (representing the total uptime in hours, without the full days counting.
Any ideas?

In PostgreSQL you can extract the epoch from timestamps: the seconds elapsed since 1970-01-01 00:00:00. With those values you can easily construct your desired output:
SELECT "start", "end", format('%s:%s:%s',
(up_secs / 3600)::int::text, -- hours
lpad(((up_secs % 3600) / 60)::int::text, 2, '0'), -- minutes
lpad((up_secs % 60)::text, 2, '0')) AS uptime -- seconds
FROM (
SELECT "start", "end",
(extract(epoch from "end") - extract(epoch from "start")) AS up_secs
FROM uptime) sub;
The lpad() function makes the minutes and seconds always two characters wide.

Related

How to convert a timestamp into seconds (and fractions) in PostgreSQL

I'm trying to get some (application) performance data from a PostgreSQL database by looking at two dates in a record, subtracting them and getting the result as a number of seconds with fractions.
It seems I'm able to get a timestamp which includes hours, minutes, seconds, and milliseconds, or I can get just the seconds (and fractions) without e.g. the minutes or I can get a UNIX timestamp which is only seconds (without the milliseconds). Is there a convenient way to convert a timestamp to seconds+millis?
Example:
SELECT extract(SECOND FROM TIME '00:01:02.1234') as secs;
secs
--------
2.1234
I was hoping to get 62.1234 (that's 1 * 60 + 02.1234) as the return value for overall seconds, not just the "seconds component" from the time value.
Is there an existing function to do that, or do I have to EXTRACT each part, multiply, and add each component together?
Use EPOCH:
SELECT extract(EPOCH FROM TIME '00:01:02.1234') as secs; 62.1234

postgres time conversion hh:mm:ss.us to hh:mm

Using PostgreSQL database for my attendance application.
I have a table with IN and out times (hh:mm:ss.us format).
When I subtract the times (OUT -IN) to calculate the working hours, results are not as expected due to precision.
If IN Time is "22:12:56.09"
& OUT TIme is "22:14:06.06" the difference considering only HH:mm should be 00:02 but it actually shows "00:01:09.97" which becomes "00:01" in excel using only HH:mm.
I am trying to do the time conversion from hh:mm:ss.us to hh:mm (time format) so that I can subtract the time and get the desired output.
I have done similar things in SQL Server but I did not find any function in PostgreSQL. Please advise.
First you need to truncate the seconds. Then subtract to get desired result
select
to_char(
(
to_char('22:14:06.06' :: time, 'HH24:MI'):: time -
to_char('22:12:56.09' :: time, 'HH24:MI'):: time
),
'HH24:MI'
)
Result: 00:02
General Solution:
select
to_char(
(
to_char(out, 'HH24:MI'):: time - to_char(in, 'HH24:MI'):: time
),
'HH24:MI'
)
Here the purpose of to_char() is to format result to hours:minutes and not to include seconds.
Postgres includes seconds in interval by default.
You can use the date_trunc function with timestamp.
It would work something like this:
select date_trunc('minute', out) - date_trunc('minute', in)
This would set a minute level precision on the timestamp and convert HH:mm:ss to HH:mm:00

Issue selecting timespan values in KDB

I am facing an issue while selecting the following following timespan :
t:([] date:2#.z.d ; time: 10D21:28:47.425287000 10D12:18:23.287989000 )
date time
--------------------------------
2018.03.15 10D21:28:47.425287000
2018.03.15 10D12:18:23.287989000
when i run the following query, i am not getting the second record back
select from t where time within (12:00;13:00)
I am expecting the 2nd record from the table :
date time
-------------------------------
2018.03.15 10D12:18:23.287989000
Is the 10 in the time value 10D12:18:23.287989000 intentional ?
The reason behind the data not coming back is the time (type timespan ) is actually not the nano seconds since midnight ; as per the table it is 10 days plus nanos since midnight
To select the data only on the basis of time :
q)select from t where (`time$(`date$0)+time) within (12:00;13:00)
date time
-------------------------------
2018.03.15 10D12:18:23.287989000
Try adding the date and time from the table , you would see the date forwarded by 10 days
q)select date+time from t
date
-----------------------------
2018.03.25D21:28:47.425287000
2018.03.25D12:18:23.287989000
The timespan is basically nDhh:mm:ss.sssssssss , where n is relative to midnight. If its 0 then it's current day otherwise its +/- n days (depending on whether n is positive or negative).
try running the following , it will return you the difference between the 2 timestamps as a timespan with n=10.
q)2018.03.25D10:12:00.000000000 - 2018.03.15D10:00:00.000000000
10D00:12:00.000000000
Although you should fix your timestamps (there shouldn't be a 10D) if you're in a situation where you can't fix the upstream data but you believe the timestamps to actually be correct, then you can strip away the 10D as follows:
q)update mod[;`long$10D]time from t
date time
-------------------------------
2018.03.16 0D21:28:47.425287000
2018.03.16 0D12:18:23.287989000

inconsistency between month, day, second representation of interval data type

I understand why postgresql uses month,day and second fields to representate the sql interval datatype. A month is not always the same length and a day can have 23, 24 or 25 hours if a daylight savings time adjustment is involved. this is from postgresql documentation.
But I then do not understand why this is not consequently handled both for months and days. see the following query which calculates an exact interval where the number of seconds between two points in time is exactly calculatable:
select ('2017-01-01'::timestamp-'2016-01-01'::timestamp); -->366 days.
postgresql chooses to give a result in days. not in months and not in seconds.
But why is the result days and not seconds? it is NOT defined how long days are (they can be 23,24 or 25 hours long). so why does he not give output in seconds?
Then since the length of months is also not defined, why doesn't postgresql give an output of 12 month instead of 366 days?
He does not care that the length of days is not defined, but obviously he cares that the length of month is not defined.
Why this asymmetrie?
For further explanation, see this query:
select ('10 days'::interval-'24 hours'::interval); --> 10 days -24:00:00
you see that postgresql correctly refuses to answer with 9 days. He is pretty aware of the problem that days and hours cannot be interchanged. But then again why does the first query return days?
I can't answer your question, but I think I can point you in the right direction. I think the book SQL-99 Complete, Really is the most accessible source for understanding SQL intervals. It's available online: https://mariadb.com/kb/en/sql-99/08-temporal-values/.
SQL standards describe two kinds of intervals: year-month intervals and day-time intervals. It does this to prevent month parts and day parts from appearing in the same interval, because, as you already know, the number of days in a month is ambiguous. The number of days in the interval '3' month depends on which three months you're talking about.
I think this is the verbose, standard SQL way to write your first query.
select cast(timestamp '2017-01-01' - timestamp '2016-01-01' as interval day to hour) as new_column;
new_column
interval day to hour
--
366 days
I suspect that you'll find that SQL standards have rules for what a SQL dbms is supposed to do when things like interval day to hour are omitted. PostgreSQL might or might not follow those rules.
postgresql chooses to give a result in days. not in months and not in seconds.
Standard SQL prevents month parts and day parts from appearing in the same interval. Also, the range of valid seconds is from 0 to 59.
select interval '59' second;
interval
interval second
--
00:00:59
select interval '60' second;
interval
interval second
--
00:01:00

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.