Get days between tow dates - oracle

Have a date in the table with format 10/04/14
then use this to_char(nameofcolumn, 'yyyymmdd')) to get this
20140410
Now, need rest a this value the sydate
I use this
select nameofcolumn,
to_char(nameofcolumn, 'yyyymmdd')) - to_char(sysdate, 'yyyymmdd') AS days
from
table;
But te result for example 07/07/14 return 300 days when is 90

Why are you converting these into strings? You can perform basic date arithmetic without converting them:
select nameofcolumn,
nameofcolumn - sysdate AS days
from
table;

I can't add comments so i will post a little addition as a separate answer.
SELECT to_date('07/07/2014','dd/mm/yyyy') - SYSDATE AS days FROM dual;
would return a number with a floating point instead of an integer. You've got to do either
SELECT trunc(to_date('07/07/2014','dd/mm/yyyy') - SYSDATE) AS days FROM dual;
or
SELECT to_date('07/07/2014','dd/mm/yyyy') - trunc(SYSDATE) AS days FROM dual;
depeding on what exactly you want to achieve.

Related

mixing and matching data types to produce a desired date format of mm/dd/yyyy

Let me start with I have a confused Oracle table that has 2 particular columns in it, 1 for issuedate VARCHAR2(10) and one for compdate VARCHAR2(8). The NLS_DATE_FORMAT for the system session is 'YYYY-MM-DD HH24:MI:SS'. I cannot change the NLS_DATE_FORMAT as there are a significant set of SELECT's that use this format to convert other timestamps into dates.
issuedate is 'MMDDYYYY' COMPDATE is 'MM/DD/YYYY'
here are the portions of the Select in question
co.issuedate issued,
to_date(substr(ae.cdts, 1,8)) DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8)) DATE_JOB_CLOSED,
co.compdate WORKED,
The goal is to subtract
issued-WORKED
and get the result in number of days.
Guidance is appreciated
The first part of the solution should be to fix your table so that you are storing date values in a DATE data type and NOT in a VARCHAR2.
The second part of the solution should be to go back through all your old code and fix any instances where you use TO_DATE or TO_CHAR to make sure they always are passed a second argument to explicitly set the format model and to never rely on an implicit format model set by the NLS_DATE_FORMAT session parameter.
Since you are storing it as a VARCHAR2, just use TO_DATE and subtract to get the difference:
SELECT co.issuedate issued,
TO_DATE(substr(ae.cdts, 1,8), 'YYYYMMDD') DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8), 'YYYYMMDD') DATE_JOB_CLOSED,
co.compdate WORKED,
TO_DATE(co.issuedate, 'MMDDYYYY') - TO_DATE(co.compdate, 'MM/DD/YYYY')
AS days_difference
FROM ...;
and get the result in mm/dd/yyyy format.
If you really want the difference in days, months and years then it gets more complicated:
SELECT issued,
DATE_JOB_OPENED,
DATE_JOB_CLOSED,
worked,
TO_CHAR(
EXTRACT(MONTH FROM (issued_date - comp_date) YEAR TO MONTH),
'FM00'
)
||'/'||
TO_CHAR(
issued_date - ADD_MONTHS(comp_date, FLOOR(MONTHS_BETWEEN(issued_date, comp_date))),
'FM00'
)
||'/'||
TO_CHAR(
EXTRACT(YEAR FROM (issued_date - comp_date) YEAR TO MONTH),
'FM0000'
) AS difference
FROM (
SELECT co.issuedate issued,
TO_DATE(substr(ae.cdts, 1,8), 'YYYYMMDD') DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8), 'YYYYMMDD') DATE_JOB_CLOSED,
co.compdate WORKED,
TO_DATE(co.issuedate, 'MMDDYYYY') AS issued_date,
TO_DATE(co.compdate, 'MM/DD/YYYY') AS comp_date
FROM table_name co
-- ...
);
Which, for the sample data:
CREATE TABLE table_name (issuedate, compdate) AS
SELECT '10292021', '01/01/2021' FROM DUAL;
Outputs for the co related columns:
ISSUED
WORKED
DIFFERENCE
10292021
01/01/2021
10/28/0000
db<>fiddle here

How do I separate the time and date in SQL navigator?

I am trying to separate the time and date in one column to be independent off each other. I am new at writing scripts
this is my query:
select
*
from
[tablename]
where
to_date([column_name]) in ( '15-Jun-2021', '16-Jun-2021' )
and
to_char([column_name],'dd-Mon-yyyy HH:MM:ss') < '15-Jun-2021 19:54:30'
The way you put it, it would be
select *
from your_table
where date_column >= date '2021-06-15'
and date_column < to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss')
because
date_column should be of date datatype. If it isn't, you'll have problems of many kinds in the future. Therefore,
don't to_date it, it is already a date
don't to_char it either, because you'd be comparing strings and get unexpected result. Use that function when you want to nicely display the result
the second condition you wrote makes the first one questionable. If date_column is less than value you wrote, then you can omit date '2021-06-16' from the first condition because you won't get any rows for that date anyway
date literal (date '2021-06-15') sets time to midnight, so condition I wrote should return rows you want
SQL> select date '2021-06-15' first,
2 to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss') second
3 from dual;
FIRST SECOND
------------------- -------------------
15.06.2021 00:00:00 15.06.2021 19:54:30
SQL>

Conversion of number to date affect the performance in oracle

I have below query where the DT_ID is number data type column and the value stored in this column is date in the format 'YYYYMMDD'.
In my below query I want to get the previous week data from Monday till Sunday for weekly reporting and this query works very fast.
select ID,NAME
from TEST_REPORT
where
DT_ID between 20170904 and 20170910;
But this is hardcoded date and I want to make it dynamic. I tried with this query:
select ID,NAME
from TEST_REPORT
where
DT_ID>= next_day(trunc(sysdate), 'MONDAY') - 14 and
DT_ID< next_day(trunc(sysdate), 'MONDAY') - 7;
But it gives this error:
expecting Number and got date
When I convert this number to date like below query it's resulting a lot of performance issue. Is there any other way Ican make it dynamic with better performance?
select ID,NAME
from TEST_REPORT
where
to_date(DT_ID,'YYYYMMDD') >= next_day(trunc(sysdate), 'MONDAY') - 14 and
(DT_ID,'YYYYMMDD') < next_day(trunc(sysdate), 'MONDAY') - 7;
You can convert the date values to strings and then to numbers:
select ID,NAME
from TEST_REPORT
where DT_ID >= to_number (to_char (next_day(trunc(sysdate), 'MONDAY') - 14,
'YYYYMMDD'))
and DT_ID < to_number (to_char (next_day(trunc(sysdate), 'MONDAY') - 7,
'YYYYMMDD'));

How to generate diff between TIMESTAMP and DATE in SELECT in oracle 10

I need to query 2 tables, one contains a TIMESTAMP(6) column, other contains a DATE column. I want to write a select statement that prints both values and diff between these two in third column.
SB_BATCH.B_CREATE_DT - timestamp
SB_MESSAGE.M_START_TIME - date
SELECT SB_BATCH.B_UID, SB_BATCH.B_CREATE_DT, SB_MESSAGE.M_START_TIME,
to_date(to_char(SB_BATCH.B_CREATE_DT), 'DD-MON-RR HH24:MI:SS') as time_in_minutes
FROM SB_BATCH, SB_MESSAGE
WHERE
SB_BATCH.B_UID = SB_MESSAGE.M_B_UID;
Result:
Error report -
SQL Error: ORA-01830: date format picture ends before converting entire input string
01830. 00000 - "date format picture ends before converting entire input string"
You can subtract two timestamps to get an INTERVAL DAY TO SECOND, from which you calculate how many minutes elapsed between the two timestamps. In order to convert SB_MESSAGE.M_START_TIME to a timestamp you can use CAST.
Note that I have also removed your implicit table join with an explicit INNER JOIN, moving the join condition to the ON clause.
SELECT t.B_UID,
t.B_CREATE_DT,
t.M_START_TIME,
EXTRACT(DAY FROM t.diff)*24*60 +
EXTRACT(HOUR FROM t.diff)*60 +
EXTRACT(MINUTE FROM t.diff) +
ROUND(EXTRACT(SECOND FROM t.diff) / 60.0) AS diff_in_minutes
FROM
(
SELECT SB_BATCH.B_UID,
SB_BATCH.B_CREATE_DT,
SB_MESSAGE.M_START_TIME,
SB_BATCH.B_CREATE_DT - CAST(SB_MESSAGE.M_START_TIME AS TIMESTAMP) AS diff
FROM SB_BATCH
INNER JOIN SB_MESSAGE
ON SB_BATCH.B_UID = SB_MESSAGE.M_B_UID
) t
Convert the timestamp to a date using cast(... as date). Then take the difference between the dates, which is a number - expressed in days, so if you want it in minutes, multiply by 24*60. Then round the result as needed. I made up a small example below to isolate just the steps needed to answer your question. (Note that your query has many other problems, for example you didn't actually take a difference of anything anywhere. If you need help with your query in general, please post it as a separate question.)
select ts, dt, round( (sysdate - cast(ts as date))*24*60, 2) as time_diff_in_minutes
from (select to_timestamp('2016-08-23 03:22:44.734000', 'yyyy-mm-dd hh24:mi:ss.ff') as ts,
sysdate as dt from dual )
;
TS DT TIME_DIFF_IN_MINUTES
-------------------------------- ------------------- --------------------
2016-08-23 03:22:44.734000000 2016-08-23 08:09:15 286.52

Query sysdate against field in SQL Developer

SELECT LAST_MAINTAIN, PLANE_ID
FROM PLANE
WHERE MONTHS BETWEEN(
(TO_DATE('sysdate', 'MM/DD/YYYY'),
TO_DATE('LAST_MAINTAIN', 'MM/DD/YYYY')))
>24;
I am trying to select Last_Maintain, a date field, from the Plane table and return results that have 2 years between today's date and the last maintenance. Does anyone know what is wrong? I have a feeling I am using months between incorrectly but I'm not sure. Thanks
Edit: Adjusted location of sysdate and Last_Maintain, still erroring out saying I'm missing a parentheses (right), even though I went through all my parentheses without seeing one missing.
Edit2: Tried out
SELECT *
FROM plane
WHERE MONTHS BETWEEN (sysdate, last_maintain ) > 24;
Still telling me I need more parentheses.
Edit3: Problem is resolved, here is the final code that worked:
SELECT *
FROM plane
WHERE MONTHS_BETWEEN (sysdate, last_maintain) > 24;
Don't call to_date on a date. to_date converts a string to a date. It would only make sense to pass a string to to_date.
sysdate is a function that returns a date. That is very, very different from a literal string sysdate
You probably want
SELECT *
FROM plane
WHERE months_between( sysdate, last_maintain ) > 24
MONTHS_BETWEEN returns the result as first - second, so in your case, all values are < 0. Put sysdate first.
From Oracle doc:
"If date1 is earlier than date2, then the result is negative"

Resources