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
)
Related
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
I already have a table built in oracle. I'm trying to insert some data that looks like this:
But, I can't seem to be able to add the DATE together with the ID, YEAR and INDICATOR.
I manage to get the DATE from 1/1/2019 7:00:00 PM - 12/31/2019 7:00:00 PM.
CODE:
INSERT INTO TABLE(DATE)
select to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + rownum -1 dt from dual
connect by level <= to_date('05-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') -
to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + 1;
When I exclude DATE, it looks like this:
CODE:
INSERT INTO TABLE (ID, YEAR, INDICATOR)
Values (sequ.nextval, '2019', 'X') ;
I tried to combine the two codes but it doesn't work. Is there any other ways I can do to make it works? Or I'm doing it the wrong way?
The only change data is the DATE because I need it to be 365 days of 2019.
YEAR and INDICATOR remain the same for all data.
Is this what you want?
insert into table(id, "date", "year", indicator)
select rownum, dt, extract(year from dt), 'X'
from (select to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + rownum - 1 as dt
from dual
connect by level <= to_date('05-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') -
to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + 1
) t;
Even shorter (assuming you can calculate your current year):
insert into table( id, date, year, indicator)
select sequ.nextval, to_date('31-12-2018 07:00:00', 'DD-MM-YYYY HH24:MI:SS') + rownum, 2019, 'X' from all_objects where rownum <= 365
Or, if you prefer not to use the ALL_OBJECTS table:
insert into table( id, date, year, indicator)
select sequ.nextval, to_date('31-12-2018 07:00:00', 'DD-MM-YYYY HH24:MI:SS') + level, 2019, 'X' from dual connect by level <= 365
I have a column LOGIN_DATETIME from LOGIN table
The column is varchar2 has values in two format
20-11-2018 01:00:00
20-07-2018 14:00
I need to derive a varchar value from this column with the following format
dd-mmm-yyyy hh:mi am/pm
Result expected
20-Nov-2018 01:00 AM
20-Jul-2018 02:00 PM
I tried like
Format 1:
SELECT TO_CHAR(TO_DATE(LOGIN_DATETIME, 'DD-mm-yyyy hh:mi:ss'), 'dd-mmm-yyyy hh:mi AM')
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
Format 2:
SELECT TO_CHAR(TO_DATE(LOGIN_DATETIME, 'DD-mm-yyyy hh:mi'), 'dd-mmm-yyyy hh:mi AM')
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
It's not working.
You could use this only one query:
SELECT
CASE
WHEN LENGTH(login_datetime) = 19 THEN TO_CHAR(TO_DATE(login_datetime, 'DD-MM-YYYY HH24:MI:SS'), 'DD-Mon-YYYY HH:MI AM')
WHEN LENGTH(login_datetime) = 16 THEN TO_CHAR(TO_DATE(login_datetime, 'DD-MM-YYYY HH24:MI'), 'DD-Mon-YYYY HH:MI AM')
END AS login_datetime
FROM login
ORDER BY 1;
Tested ok in rextester
Use case and select format based on field length
SELECT
CASE WHEN LENGTH(LOGIN_DATETIME) = 16 THEN TO_CHAR(TO_DATE(LOGIN_DATETIME, 'dd-mm-yyyy hh24:mi'), 'dd-mm-yyyy HH:mi AM')
ELSE TO_CHAR(TO_DATE(LOGIN_DATETIME, 'dd-mm-yyyy hh:mi:ss'), 'dd-mm-yyyy HH:mi AM')
END
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
That was easy one I dunno the syntax of SQL it was mon not mmm in date format
SELECT
TO_char(to_timestamp (LOGIN_DATETIME, 'DD-MM-RRRR HH24:MI:SS.FF'), 'DD-Mon-YYYY HH12:mi AM')
from LOGIN
WHERE LOGIN_DATETIME is NOT null;
OR
SELECT
TO_char(to_timestamp (LOGIN_DATETIME, 'DD-MM-YYYY HH24:MI:SS.FF'), 'DD-Mon-YYYY HH12:mi AM')
from LOGIN
WHERE LOGIN_DATETIME is NOT null;
The both formats work in one query itself.
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);
SELECT
TO_CHAR((current_timestamp), 'YYYY-MM-DD HH:MM:SS AM') AS curr_time, current_timestamp, dbtimezone
FROM dual;
The result is:
curr_time 2014-05-22 12:05:23 PM
current_timestamp 22-MAY-14 12.39.23.447181000 PM ASIA/CALCUTTA
dbtimezone +00:00
why do curr_time and current_timestamp differ by minutes?
because MM are month, not minutes... (and 05 is... may)
You have to use MI
Change your format to
'YYYY-MM-DD HH:MI:SS AM'