PostgreSQL get time difference between timestamps - sql

I've looked at many SO questions related to this but I can't seem to get anything to work. I'm not very good with semi complex SQL queries.
I want to get the difference between the current time and a column that is in unix timestamp in hours.
I'm not sure what I'm doing wrong or right for that matter. The goal is to only pull the rows that is less than 24 hours old. If there is a better way or example that works that would be great.
I tried several answers from here Timestamp Difference In Hours for PostgreSQL
I can't get this query to work no matter how many different ways I try it. wc.posted is a bigint store as unix timestamp
SELECT w.wal_id, wc.com_id, w.posted AS post_time, wc.posted AS com_time
FROM wall as w LEFT JOIN wall_comments as wc ON w.wal_id=wc.wal_id
WHERE (EXTRACT(EPOCH FROM wc.posted)) > current_timestamp - interval '24 hours'
Then the Error:
ERROR: function pg_catalog.date_part(unknown, bigint) does not exist
LINE 1: ... wall_comments as wc ON w.wal_id=wc.wal_id WHERE (EXTRACT(EP...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function pg_catalog.date_part(unknown, bigint) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 148
Here is a simplified fiddle

From the fine manual:
A single-argument to_timestamp function is also available; it accepts a double precision argument and converts from Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp with time zone. (Integer Unix epochs are implicitly cast to double precision.)
So to convert your bigint seconds-since-epoch to a timestampz:
to_timestamp(wc.posted)
Perhaps you're looking for this:
WHERE to_timestamp(wc.posted) > current_timestamp - interval '24 hours'

Try:
SELECT EXTRACT(EPOCH FROM (timestamp_B - timestamo_A))
FROM TableA
Details here: EXTRACT.

Try this out i am sure this will help you
select field_1,field_2,field_3 from schema_name.table_name Where
ROUND(EXTRACT(EPOCH FROM (cast(now() as timestamp) - cast(your_time_field as timestamp)))/60) > 1440;

The error message anounce :
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Indeed, the simplest solution is to add an explicit timestamp type cast
SELECT w.wal_id, wc.com_id, w.posted AS post_time, wc.posted AS com_time
FROM wall as w LEFT JOIN wall_comments as wc ON w.wal_id=wc.wal_id
WHERE (EXTRACT(EPOCH FROM wc.posted::timestamp)) > current_timestamp - interval '24 hours'
Notice the cast :
wc.posted::timestamp

Related

SQLite strftime and datetime conversation for PostgreSQL

I've tried finding an answer to this question but haven't been entirely successful (or maybe I just don't understand the PostgreSQL documentation).
I am using this function in SQLite:
datetime (message.date / 1000000000 + strftime ("%s", "2001-01-01"), "unixepoch", "localtime")
message.date is a large integer that can be converted to a date starting in 1987 e.g. 550535817000000000
strftime gives me 978307200
I am attempting to recreate this function in postgresql but am definitely missing something because I keep getting errors or incorrect output. A few attempts are below:
// Gives SQL Error [42883]: ERROR: operator does not exist: timestamp with time zone + timestamp with time zone
Hint: No operator matches the given name and argument types. You might need to add explicit type casts. Position: 51
TO_TIMESTAMP((message.date / 1000000000)) + TO_TIMESTAMP('2001-01-01', 'YYYY-MM-DD HR24:MI:SS')
// Date in 1987 with TZ -7 e.g. 1987-05-12 16:36:38.000 -0700
TO_TIMESTAMP((message.date / 1000000000))
// 2001-01-01 00:00:00.000 -0800
TO_TIMESTAMP('2001-01-01', 'YYYY-MM-DD HR24:MI:SS'),
I'm pretty sure I'm missing something. Can anyone help direct me to the right solution?
UPDATE:
The solution below based on #matbalie 's feedback -- this date is based on Messages chat.db date in the message table.
to_timestamp((message.date / 1000000000)::integer + EXTRACT(EPOCH FROM '2001-01-01'::date)::integer) message_date,

How to use PostgreSQL to calculate the completion time of two timestamp records?

I have an invitations table with the following fields:
Invitations: id, created_at, completed_at
I am working to write a PostgreSQL query that breaks down the data by weekly cohorts (last 7 days) and show the average completion time (the difference between created_at and completed_at in days). FYI, it's possible for completed_at to be null, meaning not completed.
Here is what I have so far:
SELECT TRUNC(DATE_PART('day', CURRENT_DATE - i.created_at )/7) AS weeks_ago,
date(min(i.created_at)) AS "Date Start",
date(max(i.created_at)) AS "Date End",
count(DISTINCT i.id) AS "Total Num Invites",
TIMESTAMPDIFF('day', i.created_at, i.completed_at)
FROM invitations i
GROUP BY weeks_ago
ORDER BY weeks_ago ASC;
This is erroring with:
ERROR: function timestampdiff(unknown, timestamp without time zone, timestamp without time zone) does not exist
LINE 5: TIMESTAMPDIFF('day', i.created_at, i.completed_at)
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
, Time: 0.085000s
I'm using PostgreSQL, what am I doing wrong here?
TIMESTAMPDIFF is not natural of PostgreSQL. See here: Postgresql date/time functions.
In PostgreSQL, date operations are like number operations.
Example:
SELECT '2020-01-05 00:01:05'::timestamp - '2020-01-02 00:05:05'::timestamp
-- you get: 2 days 23:56:00
So, to simulate TIMESTAMPDIFF(SQL_TSI_DAY, i.created_at, i.completed_at) you have to do:
DATE_PART('day', i.completed_at - i.created_at)
Wiht the previous example you have:
SELECT DATE_PART('day', '2020-01-05 00:01:05'::timestamp-'2020-01-02 00:05:05'::timestamp)
-- you get: 2
Your biggest hint is ERROR: function timestampdiff(unknown,. This is telling you that it does not know what datatype the value you are giving the function is. TIMESTAMPDIFF() requires the first parameter to be one of a defined list of constants. In your case SQL_TSI_DAY, like:
TIMESTAMPDIFF(SQL_TSI_DAY, i.created_at, i.completed_at)
This link might be helpful. It gives some details on the TIMESTAMPDIFF() function.
EDIT: Replaced the link above. The first link I posted had some typos and incorrect data.

Why do I get an incompatible value type for my column?

I am trying to calculate the difference between two dates in an oracle database using a JDBC connection. I followed the advice from this question using a query like this:
SELECT CREATE_DATE - CLOSED
FROM TRANSACTIONS;
and I get the following error:
Incompatible value type specified for
column:CREATE_DATE-CLOSED. Column Type = 11 and Value Type =
8.[10176] Error Code: 10176
What should I change so I can successfully calculate the difference between the dates?
note: CREATE_DATE and CLOSED both have TIMESTAMP type
The answer you found is related to date datatypes, but you are dealing with timestamps. While substracting two Oracle dates returns a number, substracting timestamps produces an interval datatype. This is probably not what you want, and, apparently, your driver does not properly handle this datatype.
For this use case one solution is to cast the timestamps to dates before substracting them:
select cast(create_date as date) - cast(closed as date) from transactions;
As it was mentioned, it seems that JDBC cannot work with the INTERVAL datatype. What about casting it with the EXTRACT function to the expected output as number? If you want number of seconds between those two timestamps, it would be:
SELECT EXTRACT(SECOND FROM (CREATE_DATE - CLOSED)) FROM TRANSACTIONS;
Here are list of options which might be used instead of SECOND:
https://docs.oracle.com/database/121/SQLRF/functions067.htm#SQLRF00639
When we subtract one date from another Oracle gives us the difference as a number: it's straightforward arithmetic. But when we subtract one timestamp from another - which is what you're doing - the result is an INTERVAL. Older versions of JDBC don't like the INTERVAL datatype (docs) .
Here are a couple of workarounds, depending on what you want to do with the result. The first is to calculate the number of seconds from the interval result. extract second from ... only gives us the numbers of seconds in the interval. This will be fine providing none of your intervals are more than fifty-nine seconds long. Longer intervals require us to extract minute, hour and even days. So that solution would be:
select t.*
, extract (day from (t.closed - t.create_date)) * 84600
+ extract (hour from (t.closed - t.create_date)) * 3600
+ extract (minute from (t.closed - t.create_date)) * 60
+ extract (second from (t.closed - t.create_date)) as no_of_secs
from transactions t
A second solution is to follow the advice in the JDBC mapping guide and turn the interval into a string:
select t.*
, cast ((t.closed - t.create_date) as varchar2(128 char)) as intrvl_str
from transactions t
The format of a string interval is verbose:INTERVAL'+000000001 04:40:59.710000'DAY(9)TO SECOND. This may not be useful in the Java side of the application. But with regex we can turn it into a string which can be converted into a Java 8 Duration object (docs) : PnDTnHnMn.nS.
select t.id
, regexp_replace(cast ((t.closed - t.create_date) as varchar2(128 char))
, 'INTERVAL''\+([0-9]+) ([0-9]{2}):([0-9]{2}):([0-9]{2})\.([0-9]+)''DAY\(9\)TO SECOND'
, 'P\1DT\2H\3M\4.\5S')
as duration
from transactions t
There is a demo on db<>fiddle

DATE_FROM_UNIX_DATE and UNIX_DATE both return errors on Google BigQuery

The query I'm running as a test is:
SELECT
UNIX_DATE(created_utc)
FROM `fh-bigquery.reddit_comments.2017_08`
But I keep getting this error:
Error: No matching signature for function UNIX_DATE for argument types:
INT64. Supported signature: UNIX_DATE(DATE) at [2:3]
I checked the datatype for the created_utc field and it's an integer. Casting and whatnot won't work either.
Would really appreciate any help. Thanks!
You should use TIMESTAMP_SECONDS() instead
#standardSQL
SELECT
TIMESTAMP_SECONDS(created_utc)
FROM `fh-bigquery.reddit_comments.2017_08`
LIMIT 5
Then you can use DATE() if you need date only
DATE(TIMESTAMP_SECONDS(created_utc))
UNIX_DATE() takes a String.
And DATE_FROM_UNIX_DATE() takes an INT64. SQL has a legacy problem of thinking of time ("date") in DAYS and not SECONDS like Unix. Thus:
SELECT DATE_FROM_UNIX_DATE(CAST(created_utc/86400 as INT64))
FROM `fh-bigquery.reddit_comments.2017_08`

Remove seconds from current date in Redshift (PostgreSQL)

In Amazon Redshift I'm looking to convert the current timestamp to have 0 seconds. That is go from this:
2013-12-17 12:27:50
to this:
2013-12-17 12:27:00
I have tried the following:
SELECT dateadd(second, -(date_part(second, getdate())), getdate());
ERROR: function pg_catalog.date_add("unknown", double precision, timestamp without time zone) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT dateadd(second, -cast(date_part(second, getdate()) as double precision), getdate());
ERROR: function pg_catalog.date_add("unknown", double precision, timestamp without time zone) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT getdate() - date_part(second, getdate());
ERROR: operator does not exist: timestamp without time zone - double precision
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
I'm probably missing a very simple way of doing this! Does anyone have any suggestions, please?
It's easiest to use the date_trunc() function, but that will work only while selecting:
SELECT date_trunc('minute', TIMESTAMP '2013-12-17 12:27:00');
You may preprocess data before loading data into the redshift DB, or use intermediary table and then use INSERT INTO...SELECT statement:
INSERT INTO destination_table (
SELECT date_trunc('minute', date_column), other_columns_here
FROM source_table
);
Check date_trunc()
SELECT date_trunc('minute', TIMESTAMP '2013-12-17 12:27:00');
You could format the date with:
select to_char(now(), 'YYYY-MM-DD HH24:MI:00');