Oracle - Selecting employees which were hired in the last 20 years - sql

I cannot use months_between, only playing with DATEs is allowed, so I got this:
select * from emp
where ((SYSDATE- hiredate)/(365+1/4-1/100+1/400)) >= ((SYSDATE/(365+1/4-1/100+1/400))-20);
I dont understand why i get error in
(SYSDATE/(365+1/4-1/100+1/400))-20
saying it is an invalid datatype "inconsistent datatypes: expected %s got %s" when
(SYSDATE-hiredate)/(365+1/4-1/100+1/400)
is working properly with no error, WTF?
PS: an example of using (365+1/4-1/100+1/400) is with birth date, for more precision:
((SYSDATE- birth_date)/(365+1/4-1/100+1/400)) >=18

sysdate retuns the current date and time.
In your second test case as below, you are subtracting two dates which returns
numeric value indicating the number of days between the two dates and so calculation (division was made possible).
(SYSDATE-hiredate)/(365+1/4-1/100+1/400)
In your first test case as below, you are directly trying to divide a date type value.
you cannot divide a date datatype in oracle. Instead you can add any value say x (sysdate +x), it means you are adding x days to the date value.
(SYSDATE/(365+1/4-1/100+1/400))-5
In case, you want to convert the sysdate to number you can try like below
select to_number(to_char(sysdate, 'yyyymmddhh24miss')) from dual;
Which will return you DATE+TIME like 20140608165750 for today.
(OR)
select to_number(to_char(sysdate, 'yyyymmdd')) from dual;
Result will be 20140608 (only the DATE part)

According to Oracle on subtracting two Date datatypes you'll get a Number datatype.
From Oracle docs: Reference
So this part of your query
((SYSDATE- birth_date)/(365+1/4-1/100+1/400)) >=18 returns a number, whereas
In this statement (SYSDATE/(365+1/4-1/100+1/400))-5 sysdate is still taken as a date dataype which is why you're getting the error. You can explicitly use to_number to convert sysdate into number.
Edit: Try this ((to_number(to_char(SYSDATE,'DDMMYYYY'))/(365+1/4-1/100+1/400))-5) to convert your sysdate date dataype into number datatype. So, your select query should look like this
select * from emp
where ((SYSDATE- hiredate)/(365+1/4-1/100+1/400)) >= ((to_number(to_char(SYSDATE,'DDMMYYYY'))/(365+1/4-1/100+1/400))-5);

Related

getting sql error:hour must be between 1 and 12

There is a problem with a query I use to report.I get an error comparing a value stored as a timestamp with data saved yesterday.
query:
SELECT * FROM PIECE P, PIECE_ATTRB PA WHERE P.PIECE_NUM_ID=PA.PIECE_NUM_ID
AND PA.ATTRB_CODE='PRODUCTION_CUT_DATE'
AND PA.ATTRB_AN_VALUE >=cast(TRUNC(SYSDATE-1)+ INTERVAL '00:00:00' HOUR TO SECOND AS timestamp)
AND pa.ATTRB_AN_VALUE < CAST(TRUNC(SYSDATE)+ INTERVAL '00:00:00' HOUR TO SECOND AS timestamp)
Sample value for pa.attrb_an_value : 03-FEB-21 23:43:26,000000
But I get the following error.
hour must be between 1 and 12
you can first convert the date into timestamp. Instead of ATTRB_AN_VALUE please use
to_timestamp(substr(ATTRB_AN_VALUE,1,18),'DD.MM.YYYY HH24:MI:SSFF3')
This will convert the value into 03-FEB-21 11.43.26.000000 PM and it will eliminate the error.
Since the column attrb_an_value is not a DATE or TIMESTAMP but a VARCHAR2, you cannot compare it to a date without some casting. The TO_TIMESTAMP function will take a string and convert that to a timestamp value with a given format mask.
SELECT
*
FROM
piece p,
piece_attrb pa
WHERE
p.piece_num_id = pa.piece_num_id AND
pa.attrb_code = 'PRODUCTION_CUT_DATE' AND
TO_TIMESTAMP(pa.attrb_an_value,'DD-MON-YY HH24:MI:SS,FF6') >= TRUNC(systimestamp,'DD') - INTERVAL '1' DAY AND
TO_TIMESTAMP(pa.attrb_an_value,'DD-MON-YY HH24:MI:SS,FF6') < TRUNC(systimestamp,'DD')
Note 1: This will fail as soon as a row does not contain a string matching the DD-MON-YY HH24:MI:SS,FF6 format mask.
Note 2: As others pointed out, this is a serious design flaw. No date or timestamp data should be stored in VARCHAR2 columns.
I think your problem is about formatting the date. Here's the correct formatting. Also, I thought that you wanted result set that contained PA's ATTRB_AN_VALUE values in between the beginning of yesterday and today. So, the answer contains the simplified version of compared dates.
SELECT * FROM PIECE P, PIECE_ATTRB PA WHERE P.PIECE_NUM_ID=PA.PIECE_NUM_ID
AND PA.ATTRB_CODE='PRODUCTION_CUT_DATE'
AND to_timestamp(PA.ATTRB_AN_VALUE,'DD-MON-RR HH24:MI:SS,FF') >=to_timestamp(trunc(sysdate-1))
AND to_timestamp(pa.ATTRB_AN_VALUE,'DD-MON-RR HH24:MI:SS,FF') < to_timestamp(trunc(sysdate));

Difference in dates in Oracle

I am writing the following query
SELECT
TO_CHAR(TO_DATE(data_elaborazione, 'YYYYMMDD') -
TO_DATE(DATA_INS_AGG_SDS, 'YYYYMMDD') )AS DateDiff
FROM
dual
I want to calculate the difference between the two dates, in days, but I get an error:
ORA-00904: "DATA_INS_AGG_SDS": invalid identifier
The same goes for data_elaborazione too. Data_elaborazione, DATA_INS_AGG_SDS are both varchar types that contain dates as varchar
The error you are getting is cause by you referencing columns on dual that do not exist. You'll need to select these columns from the tables they actually exist in. As for your date arithmetic, it should return a number, which does not require TO_CHAR to display, unless you have some specific formatting concerns. Here is an example of date arithmetic. The second date value has a time component. So, the two columns due the date arithmetic and display the result, the second essentially rounds down to just get the number of days to an even integer value.
Please read the comments about data types. You should always work with values in their correct data types. Avoid storing either dates or numbers as strings in the DB.
-- start test_data
with some_data(begin_date, end_date) as
(select to_date('02/15/2017','MM/DD/YYYY'), to_date('04/03/2017 09:34:12','MM/DD/YYYY HH24:MI:SS') from dual)
-- end test data
select end_date - begin_date as num_days_diff_w_time,
FLOOR(end_date - begin_date) as num_days_diff_wo_time
from some_data;

How to take differece between 2 dates of different format in SQL

I have a table with a LOAD_STRT_DTM colum. This is a date column and values are like this - 18-JUL-14 08.20.34.000000000 AM.
I want to find the data which came before 5 days.
My logic is -
Select * from Table where 24 *(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) >120
The issue is -
Select (To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) from table
This query should give the NumberOfDays between two dates. But this is not working, I Doubt, the issue is because of the format of the LOAD_STRT_DTM colum.
Please let me know where i am doint it wrong.
If your column is DATE datatype everything is ok, just shoot an:
select * from table where LOAD_STRT_DTM > sysdate - 5;
No need to convert dates to DATE datatype.
(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY'))
You don't have to convert a DATE into a DATE again. IT is already a DATE. You just need to use it for date calculations. You use TO_DATE to convert a STRING into a DATE.
For example, if you have a string value like '18-JUL-14', then you would need to convert it into date using TO_DATE. Since your column is DATE data type, you just need to use as it is.
This is a date column
I want to find the data which came before 5 days.
Simply use the filter predicate as:
WHERE load_strt_dtm > SYSDATE - 5;
NOTE : SYSDATE has both date and time elements, so it will filter based on the time too. If you want to use only the date part in the filter criteria, then you could use TRUNC. IT would truncate the time element.
I have answered a similar question, have a look at this https://stackoverflow.com/a/29005418/3989608
It looks like LOAD_STRT_DTM is a TIMESTAMP rather than a DATE, given the number of decimal points following the seconds. The only thing you have to be cautious about is that Oracle will convert a DATE to a TIMESTAMP implicitly where one of the operands is a TIMESTAMP. So the solution
WHERE load_strt_dtm > SYSDATE - 5
will work; as will
WHERE load_strt_dtm + 5 > SYSDATE
but the following will not:
WHERE SYSDATE - load_start_dtm < 5
the reason being that TIMESTAMP arithmetic produces an INTERVAL rather than a NUMBER.
first convert two dates to same format select datediff(dd,convert(varchar(20),'2015-01-01',112),convert(varchar(20),'01-10-2015',112))

1st Day of Current Year in Date Range Criteria in PS Query

I know how to select the first day of the first month of the current year in a number of different formats. The following works fine: '01-JAN-' || TO_CHAR(TO_DATE(SYSDATE),'YYYY').
However, I need to use January 1, of the current year in a date range criteria in a YTD PSoft Query:
WHERE A.effdt BETWEEN (January 1, Current_Year) AND SYSDATE.
When I use the expression '01-JAN-' || TO_CHAR(TO_DATE(SYSDATE),'YYYY') in the criteria, I get the following error:
A SQL error occurred. Please consult your system log for details.
Error in running query because of SQL Error, Code=1858, Message=ORA-01858:
a non-numeric character was found where a numeric was expected (50,380)`
You should NEVER compare LITERAL with DATE. Since, Oracle will do an IMPLICIT conversion. And, sooner or later, it would become a performance issue.
Explicitly convert the literal to date using TO_DATE.
For example,
Depending on the date value input method,
1. If you are passing the literal via some program
BETWEEN TO_DATE('01-01-2014','DD-MM-YYYY') and SYSDATE
2. If you already have the date value in table, then use TRUNC
BETWEEN TRUNC(SYSDATE, 'YYYY') and SYSDATE

Asking User to input date in sql giving ORA-00932: inconsistent datatypes: expected DATE got NUMBER Error

I am trying to input a date value from the user and then using that value in the query.
select * from TB_MNP_GTY_TRANS_STEPS where CREATE_DATETIME>=&startdate
Now when i run the sql statement in Toad and input 8/1/2012 as date data type i am getting
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
Can someone suggest where i am wrong.Note that CREATE_DATETIME is of Date Type.
You should really specify what date format you are using in your parameter:
SELECT *
FROM TB_MNP_GTY_TRANS_STEPS
where CREATE_DATETIME >= TO_DATE(&startdate, 'DD/MM/YYYY');
Read about date formats here
Currently your session is expecting the date to be in its default NLS_DATE default fomat and obviously the format of the date you're entering is different.
Explicitly specifying date formats prevents this issue from occurring.
Hope it helps...
EDIT:
If you want to pass in the 8th January 2012 then you could specify your variable value as:
08/01/2012
And your select would be:
SELECT *
FROM TB_MNP_GTY_TRANS_STEPS
where CREATE_DATETIME >= TO_DATE(&startdate, 'DD/MM/YYYY');
Depending upon your environment you might need to wrap the variable in single quotes (for TOAD you definiely will) i.e.
SELECT *
FROM TB_MNP_GTY_TRANS_STEPS
where CREATE_DATETIME >= TO_DATE('&startdate', 'DD/MM/YYYY');
The error you are getting is caused by the format of the date string you are entering not matching EXACTLY the format you are specifying (see the leading "0" before the 8 and 1 in the day and month!)
Date casting necessary
select * from TB_MNP_GTY_TRANS_STEPS where CREATE_DATETIME>=to_date(&startdate, 'MM-DD-YYYY')
and while passing parameter you should pass value in quoets as '08-09-1999'