Query sysdate against field in SQL Developer - oracle

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"

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>

The between and like functions with dates

I ran these two scripts below and they give two different results. The first did not include data for the 30th of April but the latter does. I am using oracle sql. Could someone assist?
select distinct * from a where (m_date between'01-MAY-17' AND '30-MAY-17');
select distinct * from a where m_date like '%-MAY-17';
I used the to_date function and it worked:
select distinct * from a where to_date (m_date) between'01-MAY-17' AND '30-MAY-17'
This produced the same results as with the like clause:
select distinct * from a where m_date like '%-MAY-17'
Your between clause
select distinct * from a where to_date (m_date) between'01-MAY-17' AND '30-MAY-17'
is the same as saying (pseudo-code)
...where to_date (m_date) between '01-may-17 00:00:00' AND '30-may-17 00:00:00'...
which excludes and date values on 5/30 where there is any time element other than 12AM in the morning. (Also, May does have 31 days).
It would be more correct to do the following, assuming m_date is a date data type and assuming you want all values during the month of may.
... where m_date >= to_date('01-may-17') and m_date < to_date('01-jun-17')...

compare 13digit (millisecond) unix timestamp with date in oracle

A database column (VARCHAR2 datatype) stores the date/time as 13 digit (milliseconds
) unixtimestamp format. Now when I want to compare the column with a oracle date (in question), The error thrown as 'invalid number'
I tried both ways,
converting the 13digit number to Date and compare with the date in question like below. The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
Here 'value' is 13th digit unixtimestamp column of VARCHAR2 datatype.
select
TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000,
TO_DATE('2014-04-21', 'YYYY-MM-DD')
from dummytable
-- where and TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD')
converting the date in question to 13digit unixtimestamp and comparing with the database column.The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
.
select
value,
(to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60)
from dummytable
-- where value > ((to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60))
any pointers? Thanks in advance.
[EDIT- 1 day later] I see the problem now. There are some data (other rows) for the 'value' column that are non-numeric. But I have another column say field, where always field='date' return value as 13 digit timestamp. Now I think when 'where' condition executes, although the field='date' is in the condition, it is still validating the other values for 'value' which are non-numeric. Is there a way to avoid this ?
Your code works just fine. The problem is in your data. Some of your values is not a number.
create table test
(value varchar2(13));
insert into test(value) values('2154534689000');
--insert into test(value) values('2 54534689000');
select TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000
from test
where TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD');
This code works fine. But if you uncommented the second insert, you would get exactly the same invalid number error as you get.
UPD. Allan gave you a nice hint, but i feel that it can be good to explain you a bit about views. The fact that you select from a view CAN make a difference. A view is not stored somewhere physically, when you select from it, it is just "added to your query". And then Oracle Query Optimizer starts working. Among other things, it can change the order in which your where predicates are evaluated.
For example, your the view query can have a line where value is not null and it would normally show only 'good' values. But if your query has a predicate where to_date(value,'ddmmyyyy') > sysdate, Oracle can decide to evaluate your predicate earlier, because Oracle predicts that it would "cut off" more rows, thus making the whole query faster and less momery consuming. Of course, execution will crash because of an attempt to convert a null string to date.
I believe, that Allan in his answer that he gave a link to, gave a great way to solve this problem: "wrapping" your query in a subquery that Oracle can't "unwrap":
select value
from
(select value
from my_view
where rownum > 0)
where to_date(value,'ddmmyyyy') > sysdate
Hope that helps.

Get days between tow dates

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.

Resources