I have the following code where I am trying to simply subtract 5 days from the date. The date is stored as in EPOCH time (miliseconds, 13 numbers)in the t.Date_created field. but for some reason the code does not work with the following error. Any advice would be helpful!!!
[42883] ERROR: operator does not exist: timestamp with time zone -
integer Hint: No operator matches the given name and argument types.
You might need to add explicit type casts.
Code below:
SELECT to_timestamp(t.date_Created / 1000) - 5 FROM task_mgmt.teams t LIMIT 5;
You need to subtract an interval
to_timestamp(t.date_Created / 1000) - interval '5 days'
Integers can only be subtracted directly from a date value, not from a timestamp value.
I would suggest arithmetic:
t.date_created - 5 * 24 * 60 * 60 * 1000
Related
I have two timestamp columns: arrTime and depTime.
I need to find the number of munites the bus is late.
I tried the following:
SELECT RouteDate, round((arrTime-depTime)*1440,2) time_difference
FROM ...
I get the following error: inconsistent datatype . expected number but got interval day to second
How can i parse the nuber of minutes?
If i simply subtract: SELECT RouteDate, arrTime-depTime)*1440 time_difference
The result is correct but not well formatted:
time_difference
+00000000 00:01:00 0000000
The result of timestamp arithmetic is an INTERVAL datatype. You have an INTERVAL DAY TO SECOND there...
If you want the number of minutes one way would be to use EXTRACT(), for instance:
select extract( minute from interval_difference )
+ extract( hour from interval_difference ) * 60
+ extract( day from interval_difference ) * 60 * 24
from ( select systimestamp - (systimestamp - 1) as interval_difference
from dual )
Alternatively you can use a trick with dates:
select sysdate + (interval_difference * 1440) - sysdate
from (select systimestamp - (systimestamp - 1) as interval_difference
from dual )
The "trick" version works because of the operator order of precedence and the differences between date and timestamp arithmetic.
Initially the operation looks like this:
date + ( interval * number ) - date
As mentioned in the documentation:
Oracle evaluates expressions inside parentheses before evaluating those outside.
So, the first operation performed it to multiply the interval by 1,440. An interval, i.e. a discrete period of time, multiplied by a number is another discrete period of time, see the documentation on datetime and interval arithmetic. So, the result of this operation is an interval, leaving us with:
date + interval - date
The plus operator takes precedence over the minus here. The reason for this could be that an interval minus a date is an invalid operation, but the documentation also implies that this is the case (doesn't come out and say it). So, the first operation performed is date + interval. A date plus an interval is a date. Leaving just
date - date
As per the documentation, this results in an integer representing the number of days. However, you multiplied the original interval by 1,440, so this now represented 1,440 times the amount of days it otherwise would have. You're then left with the number of seconds.
It's worth noting that:
When interval calculations return a datetime value, the result must be an actual datetime value or the database returns an error. For example, the next two statements return errors:
The "trick" method will fail, rarely but it will still fail. As ever it's best to do it properly.
SELECT (arrTime - depTime) * 1440 time_difference
FROM Schedule
WHERE ...
That will get you the time difference in minutes. Of course, you can do any rounding that you might need to to get whole minutes....
Casting to DATE first returns the difference as a number, at least with the version of Oracle I tried.
round((cast(arrTime as date) - cast(depTime as date))*1440)
You could use TO_CHAR then convert back to a number. I have never tested the performance compared to EXTRACT, but the statement works with two dates instead of an interval which fit my needs.
Seconds:
(to_char(arrTime,'J')-to_char(depTime,'J'))*86400+(to_char(arrTime,'SSSSS')-to_char(depTime,'SSSSS'))
Minutes:
round((to_char(arrTime,'J')-to_char(depTime,'J'))*1440+(to_char(arrTime,'SSSSS')-to_char(depTime,'SSSSS'))/60)
J is julian day and SSSSS is seconds in day. Together they give an absolute time in seconds.
Thanks to previous question...
I have a more simplified OR statement.
Question is instead of a IN how could I change this to a between?
TO_DATE(TO_CHAR(TO_DATE(''19700101'',''yyyymmdd'') + + (FLOOR(ph.change_date/24/60/60)))) IN (''23-DEC-2020'', ''29-DEC-2020'')
So I want to say between the 23-DEC-2020 and 29-DEC-2020 including both?
Thanks
If you want to use an index on the change_date column then perform the conversion on the literal values and convert them to epoch times (rather than converting the column's epoch time to a date, which would not allow you to use a normal index on the column):
ph.change_date BETWEEN ( DATE '2020-12-23' - DATE '1970-01-01' ) * 86400
AND ( DATE '2020-12-29' - DATE '1970-01-01' ) * 86400 + 86399
change_date seems to be in Unix timestamp format -- the number of seconds since 1970-01-01. I would recommend doing the comparison by converting constant values to the same format:
where ph.change_date >= (date '2020-12-23' - date '1970-01-01') * 24 * 60 * 60 and
ph.change_date < (date '2020-12-30' - date '1970-01-01') * 24 * 60 * 60
Note that this is index (and partition) friendly. And, the second comparison is < on the next day to get the entire day.
If you need to deal with the column as "real" dates, you can add a computed column
alter table t add column change_date_date date generated always as
(cast(date '1970-01-01' as timestamp) + change_date * interval '1' second);
You can then reference change_date_date and even define a an index on it.
You can do it with the between keyword.
For example:
to_date('2021.01.06', 'yyyy.mm.dd') between to_date('2021.01.01', 'yyyy.mm.dd') and to_date('2021.01.31', 'yyyy.mm.dd')
I think we can try like this
where <expression>
between TO_DATE('23-DEC-2020','DD-MON-YYYY') and
TO_DATE('29-DEC-2020','DD-MON-YYYY')
You can convert the epoch time(ph.change_date) to date and then compare as follows:
Date'1970-01-01' + FLOOR(ph.change_date/24/60/60) -- considering that change_date is epoch time
between date'2020-12-23' and date'2020-12-23'
columns created_at, modified_at type timestamp without timezone
Get delta in in this columns in milliseconds:
select extract(milliseconds from modified_at - created_at) as delta_millsfrom shop_order
Nice. Now I want to get delta current date and column created_at
I try this:
select id, extract(milliseconds from (EXTRACT(EPOCH FROM current_timestamp) * 1000) - created_at) as detla_mills from shop_order
But get error
:
ERROR: operator does not exist: double precision - timestamp without time zone
LINE 1: ...om (EXTRACT(EPOCH FROM current_timestamp) * 1000) - created_...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
SQL state: 42883
Character: 85
From the text of the error and examining the syntax of the failing expression, the problem is that EXTRACT(EPOCH FROM current_timestamp) is probably not a timestamp type, and definitely multiplying it by * 1000 can't sensibly result in a timestamp type (what date would be (Sep 16, 2020) times 1000, eh?). According to the error, it's a double precision, from which you can't then subtract a timestamp.
You need to subtract some base timestamp value from current_timestamp and then convert it to another type or part that you want, or else convert the base and current_timestamp in the same way to another type that can be directly subtracted for the delta (such as converting the extracted EPOCH back to a base timestamp at the start of that EPOCH.
I have two fields dateTS and closingTime.
dateTS is a normal timestamp field (e.g. 2019-07-13 22:31:10.000000)
closingTime is a HH:MM format of when a store closes (e.g. 23:00)
I need a PostgreSQL query to subtract the two field and get the number of minutes difference between them.
Using the examples given above the difference between the two fields would be 28 minutes
So far I've tried different variations of the datediff function, but it won't work.
My guess is I either have to
a. generate a fake timestamp for closingTime which is the same day as the dateTs field and subtract the 2 timestamps.
or
b. convert the hour/minutes of both field to a float and subtract the two values to get the hours difference and convert that to minutes
You can just subtract them by converting the timestamp to a time:
select closingtime - datets::time
from your_table;
That will give you an interval as the result.
To convert that to minutes you can get the number of seconds and divide it by 60:
select (extract epoch from closingtime - datets::time) / 60
from your_table;
Cast your closing time to an interval and the timestamp to time and then subtract the two. By casting the timestamp to time you are effectively discarding the date part. You can the subtract one from the other to generate the difference as an interval.
select closingTime::interval - dateTS::time...
e.g.:
# select '23:00'::interval - now()::time;
?column?
-----------------
05:31:00.031141
(1 row)
If needed you can then convert the interval to minutes:
# select extract(epoch from ('23:00'::interval - now()::time)) / 60;
?column?
------------------
327.435313083333
(1 row)
How can i subtract days to a timestamp in CrateDB SQL query?
Exist something similar to this?
TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 14 DAY)
Don't think there is a built in function but you could do something like this
SELECT DATE_FORMAT(CURRENT_TIMESTAMP - 1000*60*60*24*14) LIMIT 100
in this example (1000 * 60 * 60) * 24 * 14 (24 is to get days and 14 is your number of days)
NB. You can also cast dates into timestamp and perform similar functionality
SELECT ABS(cast('2019-01-1' AS TIMESTAMP) - CURRENT_TIMESTAMP ) / (1000*60*60*24) LIMIT 100
this will get you a number of days between now and 1st of January
So far that's all what they have in their docs
You can subtract INTERVAL from TIMESTAMP, but before any matematichal operation you need to CAST the datatype, you can do it in this way:
SELECT now() - CAST('14 day' AS INTERVAL)
Or the same function of above, but in a contracted way
SELECT now() - '14 day'::INTERVAL;
As a string to be CAST to an INTERVAL you can use a number followed by any of this:
second
minute
hour
day
week
month
quarter
year