Reputation: 745
So I have some logic that will try to grab the Value (VALUE) correlated to the previous hour if the criteria are met. The HOUR column is a TIMESTAMP with TIME ZONE column. I figured I can run the following query but got an ORA-00932 inconsistent datatypes: expected TIMESTAMP WITH TIME ZONE got NUMBER error. Is there some sort of conversion function I have to add to my 'timestamp with timezone' value?
Below is my query code:
SELECT MAX(VALUE)
FROM VALUE V
WHERE CODE = 'HI'
AND HR = '15-JAN-17 05.00.00.000000000 AM' - (1/24);
Thanks in advance.
Upvotes: 0
Views: 278
Reputation: 46219
use TO_TIMESTAMP to let '15-JAN-17 05.00.00.000000000 AM'
to datetime then minus one hour.
SELECT MAX(VALUE)
FROM VALUE V
WHERE CODE = 'HI'
AND HR = TO_TIMESTAMP('15-JAN-17 05.00.00.000000000 AM','DD-MON-RR HH.MI.SS.FF AM') - (1/24);
Upvotes: 2
Reputation: 191275
'15-JAN-17 05.00.00.000000000 AM'
is a string, not a timestamp. You can convert it to a timestamp (with no time zone) as @D-Shih suggested, but you should specify the format mask and the date language rather than relying on NLS settings:
AND HR = to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24);
or if it's a fixed value (presumably it isn't, or you could just change that literal):
AND HR = timestamp '2017-01-15 05:00:00' - (1/24);
Subtracting a number of days from a timestamp gives you a date result, so you perhaps really want to do:
AND HR = timestamp '2017-01-15 05:00:00' - interval '1' hour;
This now stays as a timestamp, but you have no time zone information. If you know the time zone you can include it in string literal and format mask, or in the timestamp literal, e.g.:
AND HR = timestamp '2017-01-15 05:00:00 America/Los_Angeles' - (1/24);
or from your original string, if that's all you have to work with, you can use from_tz()
:
AND HR = from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour;
Doing the interval subtraction last should mean that it handles DST properly.
Demo of the various conversions, starting from your string value:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF1';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF1 TZR TZD';
select
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') as a_timestamp,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24) as b_date,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - interval '1' hour as c_timestamp,
from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour as d_timestamp_tz
from dual;
A_TIMESTAMP B_DATE C_TIMESTAMP D_TIMESTAMP_TZ
--------------------- ------------------- --------------------- ---------------------------------------------
2017-01-15 05:00:00.0 2017-01-15 04:00:00 2017-01-15 04:00:00.0 2017-01-15 04:00:00.0 AMERICA/LOS_ANGELES PST
Upvotes: 2