cast(date as timestamp) comparison is incorrect - sql

When I'm executing this comparison, it is giving incorrect result.
select case when cast('06-JAN-17 12.48.14.243000000 PM' as timestamp) >
cast('06-JAN-17 08.08.57.000000000 PM' as timestamp) then 1 else 0 end from dual
the result is '0' instead of '1'. Could someone help me what is wrong in this?

You have to use TO_TIMESTAMP when you like to cast a string to TIMESTAMP properly.
when TO_TIMESTAMP('06-JAN-17 12.48.14.243000000 PM', 'DD-MON-RR HH.MI.SS.FF PM') >
TO_TIMESTAMP('06-JAN-17 08.08.57.000000000 PM', 'DD-MON-RR HH.MI.SS.FF PM')
then 1 else 0 end

You first need to convert your text literal to a date before you cast it to a timestamp. I show you an example:
select case when cast(to_date('06-01-17 12:48:14', 'DD-MM-YY HH:MI:SS') as timestamp) > cast(to_date('06-01-17 08:08:57', 'DD-MM-YY HH:MI:SS') as timestamp) then 1 else 0 end from dual
This resturns 1.
Just change my literal by yours and the passing date format and your result will work as well.

Related

Case statement based on the time

I have the following table
Based on the transaction_DT:
if the transaction between 04:00:00 PM to 08:00:00 AM + next day get "After Hour"
Between 08:00:00 AM to 04:00:00 PM within same day get "Working Hour"
Using the case statement it is not works!
CASE
WHEN ( Transacton_DT >= TO_DATE ('4:00:00 PM', 'HH:MI:SS PM')
AND Transacton_DT <= TO_DATE ('11:59:00 PM', 'HH:MI:SS PM') )
OR ( Transacton_DT >= TO_DATE ('12:01:00 AM', 'HH:MI:SS AM')
AND Transacton_DT <= TO_DATE('8:00:00 AM', 'HH:MI:SS AM') )
THEN
'After Hour'
ELSE
'Working Hour'
END AS "Shift"
Hmmm . . . how about something like this:
(case when to_char(transaction_dt, 'HH24:MI') between '08:00' and '16:00'
then 'Working hours' else 'After hours'
end)
Your code doesn't work because you are comparing a value with a time component only (well a default date component) to one with a date component.
case
when to_char(transaction_dt, 'HH24:MI') between '08:00' and '23:59'
or to_char(transaction_dt, 'HH24:MI') between '00:00' and '07:59'
then 'Working hours'
else 'After hours' end

Subtracting time in oracle sql

I am trying to subtract time from each other based on a case condition
but the error is am getting is non-numeric character found where numeric character was expected
HERE IS THE CODE
select
case
when to_date('01-JAN-2019 05:00 AM', 'HH:MI:SS AM') <
to_date('01-JAN-2019 05:00 PM', 'HH:MI:SS AM')
then round((to_date('01-JAN-2019 05:00 AM', 'HH:MI:SS AM') -
to_date('01-JAN-2019 09:00 AM', 'HH:MI:SS AM'))*24,2)
else 0
end late
from dual
One option would be using ISO 8601 standard timestamp format as
select case
when timestamp'2019-01-01 05:00:00' < timestamp'2019-01-01 17:00:00'
then
timestamp'2019-01-01 05:00:00' - timestamp'2019-01-01 09:00:00'
else interval '0' second
end as late
from dual
If you need numeric value for hour only, then consider :
select case
when timestamp'2019-01-01 05:00:00' < timestamp'2019-01-01 17:00:00'
then
extract( hour from timestamp'2019-01-01 05:00:00'
- timestamp'2019-01-01 09:00:00' )
else 0
end as late
from dual
Demo
You have to match date format and format mask:
SQL> select
2 round(
3 (to_date('01-JAN-2019 05:00 AM', 'dd-mon-yyyy HH:MI AM') -
4 to_date('01-JAN-2019 09:00 AM', 'dd-mon-yyyy HH:MI AM')
5 ) * 24, 2) result
6 from dual;
RESULT
----------
-4
SQL>
First conversion format and real string format must match. Next, convert date to timestamp before substracting, so the result is interval. Finally, extract parts needed from the interval
select
extract( day from diff ) Days,
extract( hour from diff ) Hours,
extract( minute from diff ) Minutes
from (
select CAST(to_date('01-JAN-2019 09:00 AM', 'DD-MON-YYYY HH:MI AM') as timestamp)
- CAST(to_date('01-JAN-2019 05:00 AM', 'DD-MON-YYYY HH:MI AM') as timestamp) diff
from dual
)

How to grab the value for the previous hour when the data type is TIMESTAMP with TIMEZONE

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.
'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
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);

Convert yyyy/mm/dd into dd/mm/yyyy hh24:MI:SS

I'm trying to convert data in format 2016/06/26 into 26/06/2016 00:00:00
I was trying few option all the time getting error "Invalid months name",
Any idea/advice?
Thanks
select to_date('2016/05/07 00:00:00','mm/dd/yyyy HH24:MI:SS') from dual
In order to convert a string to a date you need to convert it first to a date. Your problems is that you are trying to format a string not a date. So for you specific case it would be:
--convert it first to a date
select to_date('2016/05/07 00:00:00','yyyy/mm/dd HH24:MI:SS')
from dual
--then convert it to a string in the format you want:
select to_char( to_date('2016/05/07 00:00:00','yyyy/mm/dd HH24:MI:SS'),
'mm/dd/yyyy HH24:MI:SS' )
from dual
--since you want it as a date:
--then convert it to a string in the format you want:
select to_date( to_char( to_date('2016/05/07 00:00:00',
'yyyy/mm/dd HH24:MI:SS'),
'mm/dd/yyyy HH24:MI:SS' )
'mm/dd/yyyy HH24:MI:SS' )
from dual
If you want just to convert your string into a date no matter the format, just use the first select I showed. Thanks to #Boneist in comments for pointing it out.

12 Hours format in oracle

I have function that receive user name and return time in , time out and username in one column.
I used substring to make it into 3 columns and time out return as 24 hours format and I need it into 12 hours format.
select substr( FUN1('username'),1,5) TIMEIN ,
substr( FUN1('username'),7,6) TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;
Use the TO_CHAR function
SELECT TO_CHAR(substr( FUN1('username'),1,5), 'DD-MM-YYYY HH:MI:SS AM') TIMEIN,
TO_CHAR(substr( FUN1('username'),7,6), 'DD-MM-YYYY HH:MI:SS AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME
FROM dual;
You can do this by converting the TIMEOUT to a date using TO_DATE assuming the time is in 24 hours format, and then re-converting it to a string using TO_CHAR with the format as 12 hours format -
select to_char(to_date('13:00', 'HH24:MI'),'HH:MI AM') from dual;
Here's how your SQL in the question would look like for the TIMEOUT -
select substr( FUN1('username'),1,5) TIMEIN ,
to_char(to_date(substr( FUN1('username'),7,6), 'HH24:MI'),'HH:MI AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;