I am running this query in postgres saying error 'operator does not exist: interval + double precision' - sql

I am using this query
SELECT
(date_trunc('hour', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60 +
EXTRACT(SECOND FROM b.pub_ts),
date_trunc('hour', b.pub_ts)
from tablename b
limit 10;
ERROR: operator does not exist: interval + double precision
LINE 1: ...ur', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60 + EXTRACT...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
After #Vao said i try the output is
the actual output should be
Because then i have to apply round on the decimal but it is coming in interval.
Like this
round (((date_trunc('hour', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60) +
concat(EXTRACT(SECOND FROM b.pub_ts),' seconds')::interval,3)

instead of
+ EXTRACT(SECOND FROM b.pub_ts),
try
+concat(EXTRACT(SECOND FROM b.pub_ts),' seconds')::interval,
The idea behind is that seconds is the only part of interval (or timestamp) that can have decimals, so you need to explicitely define you add seconds with decimals - then it should accept it

The answer to question
> round((extract(epoch from ((date_trunc('hour', b.pub_ts) -
DATE '1970-01-01')* 24 * 60 * 60)) +
EXTRACT(SECOND FROM b.pub_ts))::numeric,3)
AND also if you want day to be extracted instead of eposh
(round((extract(DAY from((date_trunc('hour', b.pub_ts)
- DATE '1970-01-01')* 24 * 60 * 60)) +
EXTRACT(SECOND FROM b.pub_ts))::numeric,3) *1000 / 1000)
https://www.postgresql.org/message-id/3FCF7C40.2040505%40klaster.net

Related

Subtracting Day from Postgresql EPOCH Column

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

Timestamp Difference In minutes for PostgreSQL

I have the following query:
Select works.id, works.client_id, COALESCE(TIMESTAMPDIFF(MINUTE,works.begin_at,works.finish_at), 0) / 60 * (clients.worker_cost_hourly * works.number_of_workers + works.machines * clients.machine_cost_hourly) as cost
from works join clients on works.client_id = clients.id
where works.paid = 0
That works fine for mysql but postgresql is complaining about the TIMESTAMPDIFF... are there ways to achieve this behaviour in both DBMS with the same query?
Btw, works.begin_at and works.finish_at are defined as time
You can just substract the two times: this gives you an interval, which you can turn to seconds with extract(), and then to minutes using arithmetics:
extract(epoch from works.finish_at - works.begin_at) / 60
This returns an integer value. If you want the decimal part as well, then:
extract(epoch from works.finish_at - works.begin_at) / 60.0
EXTRACT(EPOCH FROM works.begin_at) - EXTRACT(EPOCH FROM works.finish_at))/3600 gives you the hours difference
Select works.id, works.client_id
, COALESCE(T(EXTRACT(EPOCH FROM works.begin_at) - EXTRACT(EPOCH FROM works.finish_at))/3600, 0) / 60 * (clients.worker_cost_hourly * works.number_of_workers
+ works.machines * clients.machine_cost_hourly) as cost
from works join clients on works.client_id = clients.id
where works.paid = 0

Calculate duration from Times stored as Char(4)

I am trying to calculate the duration of a service where the times in the table are stored as Char(4) HHMM. For example, the start time is 1402, which would be 14:02, and the end time is 1536, which would be 15:36.
I need it to return a duration of 94 minutes. When I tried to just convert to numeric and subtract I get 134. I have tried to convert to time, but every example I have tried gives me a conversion type message.
Just convert the value to a time, and then use DATEDIFF:
SELECT DATEDIFF(MINUTE, CONVERT(time,STUFF(StartTime,3,0,':')),CONVERT(time,STUFF(EndTime,3,0,':')))
FROM dbo.YourTable;
You can use string functions and arithmetics:
select t.*,
(left(starttime, 2) * 60 + right(starttime, 2) - left(endtime, 2) * 60 - left(endtime)) / 60 minutes_diff
from mytable t
This converts the strings to a number of seconds, substracts the values, then converts back to minutes.
You can convert the difference to minutes and then add that back to a zero time:
select convert(time,
dateadd(minute,
(((et / 100) * 60) + (et % 60)) - (((st / 100) * 60) + (st % 60)),
0)
)
from (values (1402, 1536)) v(st, et);
Here is a db<>fiddle.
Thank you everyone for the answers, but I found my answer!
DateDiff(Minute, try_cast(substring(c.start_time, 1, 2) + ':' + substring(start_time, 3, 2) as time),
try_cast(substring(stop_time, 1, 2) + ':' + substring(c.stop_time, 3, 2) as time))
Task: given two parametes as char(4)
1402, 1536 in format HHMM
Return duration in minutes: 15*60+36 - 14*60+02 => 94
Solution:
SELECT (CAST(SUBSTRING('1536',1,2) AS int)*60 + CAST(SUBSTRING('1536',3,2) AS int))
- (CAST(SUBSTRING('1402',1,2) AS int)*60 + CAST(SUBSTRING('1402',3,2) AS int));

ORACLE-SQL : how to calculate 2 time in number type?

I kept my Time data as number type (NUMBER(4,2)) and I want to calculate the column like below
2.15 (2:15 am.) - 1.45 (1:45 am)
***result***
0.30 (a half hour)
Please kindly explain me the method to calculate.
Try this one I hove it will work for u
select to_char(to_date(((to_date(to_char(09.15),'hh24.mi')-to_date(to_char(01.45),'hh24.mi'))*24*60*60),'sssss'),'hh24:mi') time from dual;
Try this code:
select (trunc(2.15)* 0.6 + (2.15 - trunc(2.15))) - (trunc(1.45)* 0.6 + (1.45 - trunc(1.45)))
as result
from YOUR_TABLE
Result: 0,30
Assuming you can get them into separate columns:
with mins_calc as
(
select (floor(mytime1) - floor(mytime2))*60 + (mod(mytime1,1)-mod(mytime2,1)) as tot_mins
from Mytable
)
select to_char(floor(tot_mins/60))||'.'||to_char(mod(tot_mins,60)) as time_diff_char
from mins_calc
Convert to hours:
select ( trunc(t1) + (t1 - trunc(t1)) * 60) -
trunc(t2) + (t2 - trunc(t2)) * 60)
) as hours
This converts the difference to fractional hours. I would advise you to leave it like that or convert to minutes.
You can convert your two 'times' to minutes; this uses bind variables to provide both numeric values as it isn't clear where you're actually getting them from:
var time_1 number;
var time_2 number;
exec :time_1 := 2.15;
exec :time_2 := 1.45;
select 60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)) as minutes_1,
60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2)) as minutes_2,
(60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)))
- (60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2))) as minutes_diff
from dual;
MINUTES_1 MINUTES_2 MINUTES_DIFF
---------- ---------- ------------
135 105 30
You can then convert the difference in minutes back to a number in the (odd) format you're using by reversing the calculation; this uses a second CTE to get the difference in minutes calculated above to simplify things and avoid repeating the long terms:
with diff (minutes) as (
select (60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)))
- (60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2)))
from dual
)
select minutes,
trunc(minutes/60) + mod(minutes, 60) / 100 as minutes_as_number
from diff;
MINUTES MINUTES_AS_NUMBER
---------- -----------------
30 .3
DATEDIFF (Transact-SQL)
This function returns the count (as a signed integer value) of the specified datepart boundaries crossed between the specified startdate and enddate.
//You can return: second, minute, day, year. In your case is minute.
SELECT DATEDIFF(minute, '2018-08-03 02:15:00am', '2018-08-03 1:45:00am');
return value: -30
if you would like to get exact (30) converted in varchar use like that.
SELECT CONVERT(varchar, ABS(DATEDIFF(minute, '2018-08-03 02:15:00am', '2018-08-03 1:45:00am')));
First use ABS() to get the absolute number (removing the (-) minus signal) and convert to varchar using CONVERT().
source: https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
ORACLE Version
SELECT TO_DATE('2000-01-02', 'YYYY-MM-DD') - TO_DATE('2000-01-01', 'YYYY-MM-DD') AS DateDiff FROM dual

Oracle SQL Date to Long and vice versa

I have the following SQL Query which converts the long number to a date , i cannot convert the date back to the long number . kindly let me know your suggestion.
SELECT to_date((( 1432550197431912935 - POWER(2,60)) /POWER(2,44)) + to_date('01-JAN-1970','DD-MON-YYYY')) from dual
Output
7/9/2013
select TO_CHAR(((TO_DATE ('09-JUL-2013','DD-MON-YYYY') -to_date('01-JAN-1970','DD-MON-YYYY')) * POWER(2,44) ) + POWER(2,60)) from dual
Output
1432549301782839296
The long values are not the same.
You are losing too much precision in your conversion to be able to go back the other way. You can get closer by using timestamps instead of dates.
Firstly your initial query was losing the time component completely:
select to_char(date '1970-01-01'
+ (1432550197431912935 - power(2, 60))/power(2, 44), 'YYYY-MM-DD HH24:MI:SS')
from dual;
2013-07-09 01:13:19
... but even with that, converting back has lost way too much:
select ((to_date('2013-07-09 01:13:19','YYYY-MM-DD HH24:MI:SS')
- date '1970-01-01') * power(2, 44)) + power(2, 60) from dual;
1432550197477589405
Which is closer than the 1432549301782839296 you got, but still quite a long way off.
Part of the problem is the precision of DATE, which is only to the second. If you use TIMESTAMP instead you can get quite close; you can see that the value to have is supposedly very precise:
select timestamp '1970-01-01 00:00:00'
+ numtodsinterval((1432550197431912935 - power(2, 60))/power(2, 44), 'DAY')
from dual;
2013-07-09 01:13:18.775670462
Converting that back is complicated by timestamp arithmetic giving interval results, which you then have to manipulate to get back to a number, first as the original number of days:
select extract(day from int_val)
+ extract(hour from int_val) / 24
+ extract(minute from int_val) / (24 * 60)
+ extract(second from int_val) / (24 * 60 * 60)
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
- timestamp '1970-01-01 00:00:00' as int_val from dual);
15895.0509117554451620370370370370370371
... and then with your power manipulation:
select ((extract(day from int_val)
+ extract(hour from int_val) / 24
+ extract(minute from int_val) / (24 * 60)
+ extract(second from int_val) / (24 * 60 * 60))
* power(2, 44)) + power(2, 60)
as x
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
- timestamp '1970-01-01 00:00:00' as int_val from dual);
1432550197431912935.09988554676148148148
Which is pretty darn close. You could trunc or round that to the nearest whole number.
Just looking at your numbers and the power manipulation each way shows that it seems to be within the precision Oracle can cope with:
select (1432550197431912935 - power(2, 60)) / power(2, 44)
from dual;
15895.050911755445156359201064333319664
select (15895.050911755445156359201064333319664 * power(2, 44)) + power(2, 60)
from dual;
1432550197431912935.000...
Even with a timestamp, you lose some of that, as that first value is going past the 9-digit fractional second limit. The part that represents the fractional seconds - once you've accounted for the 15895 hours etc. - is .0000089776673785814232865555418862 of a day, which is .77567046150943497195839881896768 seconds; the timestamp is rounding that to .775670462. So it's never going to be perfect.
That also leads one to wonder how the original number is being generated; it seems unlikely it actually represents a time down to that extreme precision, since it's below yoctoseconds. It isn't really clear if the 'precision' is actually an artefact of it being manipulated based on powers of 2, but it doesn't look very useful anyway. It's more common to use the Unix-style epoch date, counting seconds or sometimes milliseconds since the epoch date you're using anyway, if it has to be stored as a number at all. This design is... interesting.
Try using the following query:
select TO_CHAR(((TO_DATE ('09-JUL-2013','DD-MON-YYYY') -to_date('01-JAN-1970','DD-MON-YYYY')) + POWER(2,60) ) * POWER(2,44)) from dual