Date and Time Difference in Oracle SQL - sql

In Oracle SQL I have merged 4 columns (ex of column names: a_d, a_t, d_d,d_t) into 2 columns (ex of names: a_d_t and d_d_t) that are each of the format: YYYY-MMM-DD HH24:MI. I am trying to find how much time passed (days and hours), for each observation, between a_d_t (the starting time) and d_d_t (the ending time).
I have tried d_d_t - a_d_t and to_date(d_d_t)-to_date(a_d_t), but I got back the following for each: invalid identifier.
For reference the code that I used (which worked), to merge the columns is:
to_char(to_date
( to_char (a_d,'YYYYMMDD')
|| a_t,
'YYYYMMDDHH24MI'
), 'YYYY-MM-DD HH24:MI')

Your inputs are strings, so you must convert them to dates. But it is not sufficient to say to_date, you must also give proper format models.
select to_date(d_d_t, 'yyyy-mm-dd hh24:mi') - to_date(a_d_t, 'yyyy-mm-dd hh24:mi')
from < ... >
will give you the difference in days. Multiply by 24, you will get it in hours.

Considering your inputs d_d_t, a_dare string in format yyyy-mm-dd hh:mi and nls_date_format is different from it, you can try to use following query and see, if it works.
To find the duration between two date, you have to convert your date string to the date format.
select col_a, col_b, to_date(col_a,'yyyy-mm-dd hh24:mi:ss')- to_date(col_b,'yyyy-mm-dd hh24:mi:ss')duration
from x_datedur
replace col_a with ending time, col_b with starting time and x_datedur with your tablename.

Related

Oracle, finding data between two different dates

I have a table name as business_details and column name business_date whose data type is varchar2.
Now i have to find out the data between two different dates and date format like : 12-JUN-18 21:15:13
Means, 12 Jun, 2018.
Kindly help me to write a query which can fetch the data between these two dates :12-JUN-18 21:15:13 and 25-JUN-18 18:15:32
I assume that in table business_details you have an column date or something like that.
Than use something like this:
select business_date from business_details
where date between TO_DATE ('12-JUN-18 21:15:13','dd-MM-yy hh:mi:ss')
AND TO_DATE ('25-JUN-18 18:15:32','dd-MM-yy hh:mi:ss');
Assuming your business_date is actually a string in the format you've shown (and it isn't really a date your client is just showing in that format), you need to convert that to a date type, as well as converting the string literals.
select *
from business_details
where to_date(business_date, 'DD-MON-RR HH24:MI:SS')
between to_date('12-JUN-18 21:15:13', 'DD-MON-RR HH24:MI:SS')
and to_date('25-JUN-18 18:15:32', 'DD-MON-RR HH24:MI:SS');
The format model you tried to use in a comment did this:
to_date('12-JUN-18 21:15:13', 'DD-MM-YYYY HH24:MI:SS')
is using MM rather than MON, which works anyway by default - although using month numbers is safer anyway as they aren't dependent on your session language. But more importantly it uses YYYY. If you pass a 2-digit value like 18 and try to convert with YYYY you get the wrong year:
select to_date('12-JUN-18 21:15:13', 'DD-MON-YYYY HH24:MI:SS') form dual;
TO_DATE('12-JUN-182
-------------------
0018-06-12 21:15:13
In your version your business_date was being converted implicitly so would use NLS settings, which are presumably using RR already. But that means you were comparing a date in 2018 with a range in 0018, which is why nothing matched.
You could also use timestamp literals for the fixed values (unless those strings are actually being passed in from somewhere else):
select *
from business_details
where to_date(business_date, 'DD-MON-RR HH24:MI:SS')
between cast(timestamp '2018-06-12 21:15:13' as date)
and cast(timestamp '2018-06-25 18:15:32' as date);

Using TO_DATE() with AM/PM Formatting

I am trying to select some dates from a table where the format of the dates is like this:
14-APR-14 10.35.00.0000000000 AM
01-NOV-16 02.43.00.0000000000 PM
Note that the dates can be either AM or PM, but when I try to do a simple SELECT from the table such as:
SELECT * FROM MyTable
WHERE TO_DATE(MyDate, 'DD-MON-YYYY HH:MI:SS AM') > '31-DEC-2016 08:00:00 AM';
I get the error:
ORA-01855: AM/A.M. or PM/P.M. required
I've been trying to get this work for some time but with no luck. Any help here would be appreciated.
Several problems.
Your inputs are obviously strings, since they have ten decimal places and timestamps in Oracle have at most 9. Then, strings with fractions of a second can't be converted to a date with to_date - you need to use to_timestamp or else you need to remove all the fractional parts. In the solution below I only remove the last (the tenth) decimal, since you may have non-zero fractional parts in the table - although not in the sample you posted.
Then, your format mask has yyyy but your inputs have only two digits for the year (which probably means 93 means 1993 and not 2093, so the correct thing to use would be rr rather than yy). And you use : in the format mask where your inputs use .
Finally, don't even compare dates in string format: in string comparisons, 01-JAN-2015 is before 20-NOV-2013.
You probably want something like this:
select mydate
from (
select '14-APR-14 10.35.00.0000000000 AM' as mydate from dual
union all
select '01-NOV-16 02.43.00.0000000000 PM' from dual
) mytable
where to_timestamp(substr(mydate, 1, 28) || substr(mydate, -3), 'dd-MON-rr hh.mi.ss.ff AM')
> to_timestamp('31-DEC-2016 08:00:00 AM', 'dd-MON-yyyy hh:mi:ss AM');
This query compiles correctly, and it produces no rows in the output (for obvious reasons).
NOTE: In a comment you (the OP) say the mydate field is a timestamp(6) datatype. Hard to believe (you show ten decimal places), but if indeed it is a timestamp or date, then you don't need to wrap it within any to_timestamp or to_date function, it should stand alone in the left-hand side of the inequality.
From your comment:
It's actually a timestamp; not a string. Timestamp(6) to be precise
You can just use a TIMESTAMP literal:
SELECT *
FROM MyTable
WHERE MyDate > TIMESTAMP '2016-12-31 08:00:00';

Oracle to_timestamp

quick question on Oracle To_timestamp.
I have a two fields in a table that are both varchars
1 field contains the YYYYMMDD formatted value
the 2nd field contains the hh24mmss formatted value
Im trying to convert these two fields into a timestamp field,
expected output is DD/MM/YYYY HH24:mm:ss
like '7/23/2015 12:53:04'
however, it gaves me weird result...
like '7/15/0023 12:53:04'
seems year becomes day and day becomes year..
---------- heres my sql ----------------
select
to_date(to_char(to_date('20150723','yyyymmdd'),'yyyymmdd'),'yyyymmdd') dt,
to_char(to_date(SUBSTR('005304000',1,6), 'hh24miss'), 'hh24:mi:ss') tm,
TO_TIMESTAMP(
to_date(to_char(to_date('20150723','yyyymmdd'),'yyyymmdd'),'yyyymmdd') ||
to_char(to_date(SUBSTR('005304000',1,6), 'hh24miss'), 'hh24:mi:ss'), 'yyyy/mm/dd HH24:MI:SS' ) dttm
from dual
You have one layer to much in your conversion chain. And it will be much easier if you concatenate the two columns before converting them:
to_date(date_column||time_column, 'YYYYMMDDHH24MISS')
will return a date and a time (an Oracle DATE includes a time part).
Now that you have a proper date value, you can then format that as you want:
to_char(to_date(date_column||time_column, 'YYYYMMDDHH24MISS'), 'yyyy/mm/dd HH24:MI:SS')
As your "time" column doesn't contain milliseconds there is no real benefit in using to_timestamp.
But you should really fix your table, and store that information in a single DATE (or TIMESTAMP) column. Storing dates in varchar columns is always a very bad choice.

To_date returning 2 zeros in front of Year wildcard

I want to convert 'Start_date' and 'End_date' to a different format (YYYY-MM-DD HH24:MI:SS) which is different from the other format (DD/MM/YYYY HH24:MM).
When I run the command below :
Update blarg
Set test1 = 'test',
test2 = 'test',
Start_Date = To_Date('23/07/2015 22:00','YYYY-MM-DD HH24:MI:SS'),
End_Date = To_Date('24/07/2015 00:00','YYYY-MM-DD HH24:MI:SS')
Where Id = '4';
The insert in the database consists of...
Start_Date = '0023-07-20 15:22:00'
End_Date = '0024-07-20 15:00:00'
I can understand that Oracle probably just can't detect the initial date format and doesn't know where to put the values, but I was curious if you could tell Oracle the original dates wild card and then merge it with the wild card you want to turn it into.
Because it is what you specified in the code with the format mask :
'YYYY-MM-DD HH24:MI:SS'
Notice that it lobs off the 15 from 2015
So when you say: '23/07/2015` and use the mask of 'YYYY-MM-DD' , it forces it goes as so:
23 --> YYYY = 0023
etc
So to solve, rearrange the literal date to fit into the mask of YYYY-MM-DD (Leaving that as exercise for you to learn it : - )
SQL Format Models
I want to convert 'Start_date' and 'End_date' to a different format
You are mis-understanding how date (or timestamp) columns work:
DATE columns do NOT have "a format"
Any format you see when selecting your data is applied by the SQL client you are using.
If you want to see the date values in a different format, then just do so when selecting them:
select to_char(start_date,'YYYY-MM-DD HH24:MI:SS') as start_date,
to_char(end_date, ,'YYYY-MM-DD HH24:MI:SS') as end_date
from the_table;
If you always want to see dates formatted like that, change the configuration of your SQL client.

store dates in oracle

I have a table as
create table Dummy (date_created date)
in oracle.I want to store date in 'dd-mon-yyyy' (12-dec-2010) format.
How should i do this.
Please help.
In Oracle a column created with the DATE datatype just stores the date. It doesn't have a particular format, it just stores the day, month, year, hour, minute, and second. You need to convert from whatever format you have using the TO_DATE function. If you have a text string with the date in 'dd-mon-yyyy' format and you want to put this date into your table you'd use something like
INSERT INTO DUMMY (DATE_CREATED)
VALUES (TO_DATE('01-FEB-2011', 'DD-MON-YYYY');
Going the other way (from DATE column value to character string) you'd use the TO_CHAR function. If you were retrieving a value from your table and wanted to convert it to 'DD-MON-YYYY' format you'd use something like
SELECT TO_CHAR(DATE_CREATED, 'DD-MON-YYYY')
FROM DUMMY;
Share and enjoy.
Use to_date() function. In your case, the syntax would be
insert into Dummy values (to_date('08-09-2010', 'dd-mm-yyyy'));
Here is a link to the detailed help.
The DATE datatype will store date and time information (century, year, month, day, hours, minutes, and seconds) in an internal format in the database. When you get it out of the database, you can choose to display it in whatever format you like.
This information is either created using implicit conversion from a string or explicitly using either the TO_DATE function or the ANSI date literal. If you look in the v$nls_parameters view, this will tell you what the NLS_DATE_FORMAT is which is generally used for the implicit conversion. This may often be defined as DD-MON-RR, which might be why the date will come out as 23-DEC-10 when the query select sysdate from dual is run. (Not entirely sure I'm right about the nls stuff. Correct me if I'm wrong.)
However, all the date information is available if you know how to get it. The query select to_char(sysdate, 'dd-mon-yyyy hh24:mi:ss') from dual will return all the date fields.
Likewise, the insert statement shown below will create a row with a date value in it.
insert into dummy (date_created)
values (to_date('12-dec-2010 12:34:56', 'dd-mon-yyyy hh24:mi:ss'))`
This data can then be retrieved.
select date_created from dummy
This will implicitly convert the date to a character string using the NLS_DATE_FORMAT, providing the output below.
DATE_CREA
---------
23-DEC-10
The full date information is available by explicitly converting the date to a character string.
select to_char(date_created, 'DD-MON-YYYY') as date_created from dummy;
select to_char(date_created, 'DD-MON-YYYY HH24:MI:SS') as date_created
from dummy;
This will provide output in the format you require:
DATE_CREATE
-----------
23-DEC-2010
If you always use the TO_DATE and TO_CHAR functions to convert to/from a date datatype, then you will have fewer problems. Implicit conversion is useful but can cause some confusion or problems.
You can keep and eye here
http://www.techonthenet.com/oracle/functions/to_date.php
use to_date function to save a data with the format you need. I suggest to use SYSDATE updating table and when you need to read data from table use something like that:
dbms_output.put_line(TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
to solve your problem use:
to_date('08/JAN/2010', 'DD/MON/YYYY')
Just use TRUNC(YourDate) if date have time part, it will be truncate time part. Oracle have not just 'DATE' type, 'DATE' always have time part.
However if you do not specify time - it will 00:00:00.
SELECT TRUNC(SYSDATE) from dual
Result:
23-12-2010
Oracle does not support DATE without time part.
You can make it always be an integer date by adding a CHECK constraint:
CREATE TABLE dummy (date_created date CHECK (date_created = TRUNC(date_created)))
, insert it in any format you want:
INSERT
INTO dummy (date_created)
VALUES (TO_DATE('23-DEC-2010', 'dd-mon-yyyy'))
and select it in any format you want:
SELECT TO_CHAR(date_created, 'dd-mon-yyyy')
FROM dummy