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

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().

Related

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

SQL- Math with Dates

I am working out of Oracle SQL. I have some dates that may have been poorly formatted when loading.
I'm doing a basic Max(date)-Min(Date) to get the difference in days. My results are:
+000000156 00:00:00.000000
+000000149 00:00:00.000000
+00 00:00:00.000000
I want to do some basic math with these date differences (average, etc) but I get an error message.
How do I convert these strings into numbers?
My guess is that the columns are timestamps, not dates, as the results are intervals not numbers. As you've found, Oracle have not got around to overloading the standard aggregate functions for intervals (vote for this feature on the Oracle Database Ideas forum) and currently you still have to either write your own or cast the timestamps to dates.
with demo (start_date, end_date) as
( select timestamp '2019-12-31 00:00:00', timestamp '2020-06-04 00:00:00' from dual union all
select timestamp '2020-01-31 00:00:00', timestamp '2020-06-28 00:00:00' from dual
)
select end_date - start_date as elapsed_interval
, cast(end_date as date) - cast(start_date as date) as elapsed_days
from demo;
ELAPSED_INTERVAL ELAPSED_DAYS
----------------------------- ------------
+000000156 00:00:00.000000000 156
+000000149 00:00:00.000000000 149
Basic math with dates:
date + number = date + number of days (also fractions)
SELECT SYSDATE + 1 FROM DUAL; -- tomorrow
date - number = date - number of days
SELECT SYSDATE - 1/24 FROM DUAL; -- one hour ago
date - date = numbers of days between dates (also fraction of days)
date + date = impossible
months_between(date1, date2) = returns months between two dates
add_months(date, number) = adds number (months) to date
if you have a string or number and it can be the n-th day of the year (for instance 156),
you can transform in date with TO_DATE('156', 'DDD')
if you have a string with a particular format, you can transform it in date with
TO_DATE(string, format of the date you imagine)
https://www.techonthenet.com/oracle/functions/to_date.php
if you need the opposite transform, that is transforming date to char (or number), use TO_CHAR(date, format of the date)

Oracle database: getting time from total amount of minutes from the beginning of a day

Given - number of minutes (number oracle type) from the beginning of a day, e.g. 480. Need to get standard oracle time, e.g. - 08:00:00 AM. Is there any good functions to do such operation?
Better use INTERVAL 'minutes' MINUTE to add the number of minutes. Easy to understand.
your_date_time + INTERVAL '480' MINUTE
For example,
SQL> SELECT TRUNC(SYSDATE), TRUNC(SYSDATE) + INTERVAL '480' MINUTE tmstamp FROM dual;
TRUNC(SYSDATE) TMSTAMP
------------------- -------------------
11/19/2015 00:00:00 11/19/2015 08:00:00
In fact, another way which is independent of NLS settings when you have to pass the date as literal. Thus, instead of using TO_DATE, use the ANSI Date literal which uses a fixed format 'YYYY-MM-DD' and is NLS independent.
SQL> SELECT DATE '2015-11-19' curr_date, DATE '2015-11-19' + INTERVAL '480' MINUTE tmstamp
2 FROM dual;
CURR_DATE TMSTAMP
------------------- -------------------
11/19/2015 00:00:00 11/19/2015 08:00:00
UDPATE
Given - number of minutes (number oracle type) from the beginning of a day, e.g. 480
If the minutes value is not static in SQL to be hard-coded, but a PL/SQL variable, then as #AlexPoole mentioned you need to use NUMTODSINTERVAL.
For example,
NUMTODSINTERVAL(480, 'MINUTE')
Having said that,
The Oracle PL/SQL NUMTODSINTERVAL function converts an input number to its specified Interval Day to Second Unit equivalent. The allowed interval units can be DAY, HOUR, MINUTE, or SECOND.
The return type of the function is INTERVAL.
For example,
SQL> SELECT NUMTODSINTERVAL(480, 'MINUTE') intrvl FROM DUAL;
INTRVL
---------------------------------------------------------------------
+000000000 08:00:00.000000000
Just add minutes/1440 to the date, e.g.
select to_date('1.1.2015','dd.mm.yyyy')+480/1440 from dual;

Oracle DB select between dates

I would like to query number of records between night 12.01 AM to 11.59 PM but issue is, I would like to schedule this query so I cant specify any hard coded dates.
Query should pull number of records for query date between 12.01 AM to 11.59 PM.
Could someone please help me on this.
Query should pull number of records for query date between 12.01 AM to 11.59 PM.
You could do it as:
TRUNC gives you date element truncating the time portion
convert the SYSDATE into string using TO_CHAR
then concatenate the time element
finally convert everything back to DATE
SYSDATE returns the current date and time set for the operating system on which the database resides. The datatype of the returned value is DATE, and the format returned depends on the value of the NLS_DATE_FORMAT initialization parameter.
So, you don't have to hard-code any DATE value if you want to execute the query everyday.
Use the following in the filter predicate:
BETWEEN
TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY') ||' 00:01', 'MM/DD/YYYY HH24:MI')
AND
TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY') ||' 23:59', 'MM/DD/YYYY HH24:MI')
Demo
SQL> alter session set nls_date_format = 'MM/DD/YYYY HH24:MI:SS';
Session altered.
SQL> SELECT to_date(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
2 ||' 00:01', 'MM/DD/YYYY HH24:MI') start_dt ,
3 to_date(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
4 ||' 23:59', 'MM/DD/YYYY HH24:MI') end_date
5 FROM dual;
START_DT END_DATE
------------------- -------------------
05/06/2015 00:01:00 05/06/2015 23:59:00
SQL>
So, you don't have to put any hard-coded value for current date, the SYSDATE will take care of it. All you are doing is:
TRUNC gives the date element by truncating the time portion.
Then concatenating the required time element
Converting the entire string into DATE using TO_DATE
I would like to schedule this query so I cant specify any hardcord dates
To schedule the query to execute everyday, you could use DBMS_SCHEDULER.
I'm going to assume you want everything that happens during the date of interest. So you want everything from and including midnight of that day and before midnight of the next day.
declare
AsOf Date = date '2015-01-01 13:14:15';
select ...
from tablename
where tabledate >= trunc( AsOf )
and tabledate < trunc( AsOf ) + 1;
If you know the date doesn't have a time portion, just can eliminate the calls to trunc. But you may want to keep them just in case.

How to calculate hours from varchar2 fields?

I have two varchar2 date fields like clock_in and clock_out. I am inserting datetime by sysdate so the date looks like this:
Clock_In Clock_Out
12-28-13 08:00 AM 12-28-13 05:00 PM
Now I want to calculate the no of hours he work. Can you please help in this matter?
You could just convert the data to dates using the to_date function, and then subtract the two values. Since subtracting dates returns a difference in days, you can simply multiply by 24 to get the difference in hours:
SELECT (TO_DATE(clock_out, 'DD-MM-YY HH:MI AM') -
TO_DATE(clock_in, 'DD-MM-YY HH:MI AM')) * 24 AS hours_worked
FROM my_table
EDIT:
An even better solution would probably be to save clock_in and clock_out as date fields to begin with and avoid the hassle of converting in the query, but I'm not sure this is possible for the OP.