Oracle SQL - Subtracting Date types - sql

I'm trying to project a column that subtracts an employee's start time from end time to get total hours worked.
Here's what I have:
select task_name "NAME", to_char(ses_start, 'DD-MON-RR') "DATE", to_char(ses_start,'HH:MI PM') "START", to_char(ses_end, 'HH:MI PM') "END",to_number(to_char(ses_end,'HH24:MI')) - to_number(to_char(ses_start,'HH24:MI')) "TOTAL"
The TOTAL column isn't working - is it even possible to do something like this? It worked up until I added that column, with output similar to:
TASK_NAME DATE START END
----------------- ------------ ---------- -----------
create flyers 26-MAR-16 02:00 PM 04:30 PM
update website 28-MAR-16 11:00 AM 01:00 PM
So now I want a final column (preferably in hours):
TOTAL
-----
2.5
2
or, at least in hours&minutes (this is what I was trying to do)...
TOTAL
-------
02:30
02:00
Any suggestions?

you can substract Date types in oracle, it gives you a decimal number which is the duration in days
select
task_name,
to_char(ses_start, 'DD-MON-RR') DATE,
to_char(ses_start,'HH:MI PM') START,
to_char(ses_end, 'HH:MI PM') END,
round((ses_end - ses_start) * 24, 2) DURATION_IN_HOUR
...

Related

how to add the current date to time column in oracle sql

I have a table which hold only time part.
TIME
08:00
08:00
08:00
08:00
18:00
19:00
20:00
Now, i need to concatenate the time with current date. for that i tried with below code.
to_date( to_char (sysdate,'YYYYMMDD')|| Time,'HH24MI')
but that is not working as expected and getting the below error
ORA-01830: date format picture ends before converting entire input string
Can you please help me to solve this problem.
Expected output(date time format):
14-Feb-23 08:00
14-Feb-23 09:00
What datatype do you expect as result? A string?
SQL> with test (time) as
2 (select '08:00' from dual)
3 select to_char(sysdate, 'dd-Mon-yy ') || time as result
4 from test;
RESULT
---------------
14-Feb-23 08:00
If you expect date, then
SQL> with test (time) as
2 (select '08:00' from dual)
3 select to_date(to_char(sysdate, 'dd-Mon-yy ') || time, 'dd-Mon-yy hh24:mi') as result
4 from test;
RESULT
--------
14.02.23
Hm, what format is that?! My default! Modify it to something else, e.g. what you said you want but - nonetheless - value previous code returns is a valid date value:
SQL> alter session set nls_date_format = 'dd-Mon-yy hh24:mi';
Session altered.
SQL> with test (time) as
2 (select '08:00' from dual)
3 select to_date(to_char(sysdate, 'dd-Mon-yy ') || time, 'dd-Mon-yy hh24:mi') as result
4 from test;
RESULT
---------------
14-Feb-23 08:00
SQL>
You have time strings like '08:00'. And you have to_date( to_char (sysdate,'YYYYMMDD')|| Time,'HH24MI').
The expression to_char (sysdate,'YYYYMMDD')|| Time results in something like '2023021408:00'.
You want to convert this result string into a datetime (that Oracle inappropriately calls DATE) with TO_DATE: to_date('2023021408:00', 'HH24MI').
You do notice, that the string you have constructed and the format you are using don't match? Your string's format is not 'HH24MI', but 'YYYYMMDDHH24:MI'.
Hence use:
TO_DATE(TO_CHAR(SYSDATE,'YYYYMMDD') || time, 'YYYYMMDDHH24:MI')

choose from a time period oracle sql

I have timestamp date format in column FIRST_DATE and i need to choose time period from a certain hour, for ex. all from 18:00 10.05.21 to 18:00 11.05.2021
the problem is that date column in timestamp format - FIRST_DATE:
10/05/2020 0:00:03,000000 TIMESTAMP(6)
so i tried to use it:
select
count(*)
from TABLE
where to_char(FIRST_DATE, 'HH24:MI')>='18:00'
so with this way i was able to limit the start period by time, but if i add date to this my conditions stop working
and to_char(FIRST_DATE, 'DD-MON-YY')>='10-MAY-21'
how can i correct my script to select all from 18:00 10.05.21 to 18:00 11.05.2021
Don't compare dates (or timestamps) with strings. '18:00' and '10-MAY-21' are strings. Use TO_TIMESTAMP with appropriate format mask, e.g. (lines #5 and 6):
SQL> with test (first_date) as
2 (select to_timestamp('10/05/2020 23:00:03,000000', 'dd/mm/yyyy hh24:mi:ss,ff3') from dual)
3 select *
4 from test
5 where first_date between to_timestamp('10/05/2020 18:00:00,000000', 'dd/mm/yyyy hh24:mi:ss,ff3')
6 and to_timestamp('11/05/2020 18:00:00,000000', 'dd/mm/yyyy hh24:mi:ss,ff3')
7 /
FIRST_DATE
---------------------------------------------------------------------------
10.05.20 23:00:03,000000000
SQL>

Hours and minutes between 2 incorrectly formatted datetimes

So i have some timestamps in a DB and i want to get the hours and minutes difference from them
The problem is the timestamp portion is formatted incorrectly where the hour is always 12 and the minutes portion is actually the hours and the seconds is actually the minutes.
Example DB timestamp: 10/1/2020 12:08:52 AM
So in the above example the time is actually 8:52 AM not 12:08 AM
How can i convert this datetime to something i can use in order to calculate the difference in minutes and hours between these 2 oddly formatted timestamps?
My ideal end goal is something that displays the difference in the HH:MM format
EDIT: the timestamps in oracle actually look like below, and in this eaxmple the 12 means nothing and 18 is actually the hours.
Example of what I'm looking for:
01-OCT-20 12.18.44.000000000 AM - 01-OCT-20 12.12.42.000000000 AM
Output: 06:02 . so the timespan would be 6 hours and 2 minutes in this case.
Thanks,
You can turn your string to an Oracle date (resp timestamp) with to_date() (resp to_timestamp()):
to_timestamp(mystring, 'dd/mm/yyyy ss:hh12:mi am')
Then you can use date arithmetics to compute the difference. Substrating timestamps gives you an interval, which is pretty much what you seem to be looking for, so:
to_timestamp(mystring1, 'dd/mm/yyyy ss:hh12:mi am')
- to_timestamp(mystring2, 'dd/mm/yyyy ss:hh12:mi am')
as myinterval
Like so?
(my default date format is 'yyyy-mm-dd hh24:mi:ss' in Oracle ...)
WITH
indata(sdb) AS (
SELECT '10/1/2020 12:08:52 AM' FROM dual
UNION ALL SELECT '10/1/2020 12:08:52 PM' FROM dual
)
SELECT
TO_TIMESTAMP(sdb,'dd/mm/yyyy 12:hh:mi AM') AS ts
FROM indata;
-- out ts
-- out ---------------------
-- out 2020-01-10 08:52:00
-- out 2020-01-10 20:52:00

ORACLE using TO_DATE to check if item is within last hour

I have a query that I am trying to use TO_DATE to check if ERROR_DT is a data that is within one hour of the current time
Here is what I have so far
SELECT BERROR_DT FROM SomeTable
WHERE ERROR_DT>=TO_CHAR(TO_DATE( SYSDATE, 'MM/DD/YYYY HH12:MI:SS AM') -1, 'fmMM/DDfm/YYYY HH12:MI:SS AM');
Error_DT has a value of (e.g.) 5/18/2020 6:45:15 PM
When I run this I get
ORA-01830: date format picture ends before converting entire input string
I followed the said link and it still is not working. How would I fix this so that I can still remove all 0s in front of the month and the date?
I would suggest converting the date string to the corresponding date value, then do the comparison:
select berror_dt
from sometable
where to_date(error_dt, 'fmMM/DD/YYYY HH12:MI:SS AM') >= sysdate - interval '1' hour
Bottom line, you should fix your data model and store dates as a date-like datatype rather than as a string. The above predicate is not efficient, because the conversion needs to be executed for each and every value of error_dt before the filtering applies, hence defeating an existing index on the column.
Obviously wrong thing you're doing is applying TO_DATE to SYSDATE which is a function that returns DATE datatype.
What you could do is to subtract sysdate and error_dt (I presume its datatype is DATE as well) and see whether difference is less than 1 hour. As difference of two dates is number of days, you have to divide it by 24 (as there are 24 hours in a day).
Something like this:
SQL> alter session set nls_date_format = ' dd.mm.yyyy hh:mi:ss am';
Session altered.
SQL> with test (id, error_dt) as
2 (select 1, to_date('18.05.2020 10:30:15 PM', 'dd.mm.yyyy hh:mi:ss am') from dual
3 union all
4 select 2, to_date('18.05.2020 05:20:55 AM', 'dd.mm.yyyy hh:mi:ss am') from dual)
5 select t.id, t.error_dt, sysdate
6 from test t
7 where sysdate - t.error_dt < 1 / 24;
ID ERROR_DT SYSDATE
---------- ----------------------- -----------------------
1 18.05.2020 10:30:15 PM 18.05.2020 11:02:24 PM
SQL>
If ERROR_DT is a DATE value you just need to use something like
SELECT BERROR_DT
FROM SomeTable
WHERE ERROR_DT >= SYSDATE - INTERVAL '1' HOUR
or if you prefer to use old-fashioned pre-INTERVAL calculations
SELECT BERROR_DT
FROM SomeTable
WHERE ERROR_DT >= SYSDATE - (1/24)

Oracle - Using to_date, how to convert varchar to today's date

I have a table where I store the times as varchars:
Times
starttime
00:00
16:00
22:00
From this table I can convert the column to a date like this:
Select to_date(starttime,'hh24:mi') from times
This gives me the following:
01/03/2013 00:00:00
01/03/2013 16:00:00
01/03/2013 22:00:00
How can I change this query so I can prefix the time values with today's date so I get the following instead: (16/03/2013 is today's date)
16/03/2013 00:00:00
16/03/2013 16:00:00
16/03/2013 22:00:00
Thanks
to_date(to_char(sysdate, 'dd.mm.yyyy')||' '||starttime, 'dd.mm.yyyy hh24:mi')
You can add the difference between the current date and the start of the month. I prefer this to string operations as you stick with dates, but it doesn't make much difference.
You can use TRUNC() to work it out:
select to_date('09:00','hh24:mi') + ( trunc(sysdate) - trunc(sysdate, 'mm'))
from dual
SQL Fiddle
trunc(sysdate) is the earliest today and trunc(sysdate, 'mm') is the beginning of the month. Oracle's date arithmetic means that it returns a day difference between today and the beginning of the month; giving you the difference you need to add to your original TO_DATE().