HOW TO FETCH DATA BETWEEN 2 DATES IN ORACLE SQL DEVELOPER - sql

I'm new to oracle sql . I want to fetch data between 2 dates .
Date is in this format in db : 13-DEC-10
This is the query I have written but its giving me error . How to proceed next
select sum(TOTAL_AMOUNT) from table a
where trn_date between
TO_DATE(01-APR-17, 'DD-MON-YYYY') AND TO_DATE(31-MAR-17, 'DD-MON-YYYY') ;

A date does not have a format - it is stored internally to the database as 7-bytes (representing year, month, day, hour, minute and second) and it is not until whatever user interface you are using (i.e. SQL/Plus, SQL Developer, Java, etc) tries to display it to you, the user, and converts it into something you would find meaningful (usually a string) that the date has a format.
To fix your query you just need to surround the date string in single quotes and to use YY to match the 2-digit year format (otherwise Oracle will assume that 17 in the format YYYY is the year 0017 and the century will not be as you expect):
select sum(TOTAL_AMOUNT)
from table a
where trn_date between TO_DATE('01-APR-17', 'DD-MON-YY')
AND TO_DATE('31-MAR-17', 'DD-MON-YY');
However, you can also use date literals (and skip having to match the date format model):
select sum(TOTAL_AMOUNT)
from table a
where trn_date between DATE '2017-04-01'
AND DATE '2017-05-31';

Alternatively you may use the year format of RR format against centurial problems, Don't forget to keep quotes for date values, and you may prefer calling sql with bind variables :
select sum(TOTAL_AMOUNT)
from table a
where trn_date between
TO_DATE('&date_1', 'DD-MON-RR') AND TO_DATE('&date_2', 'DD-MON-RR') ; -- where date_1 is 31-MAR-17 and date_2 is 01-APR-17, in your case.
What I mentioned by centurial problems :
The RR Datetime Format Element
The RR datetime format element is similar to the YY datetime format
element, but it provides additional flexibility for storing date
values in other centuries. The RR datetime format element lets you
store 20th century dates in the 21st century by specifying only the
last two digits of the year.
If you use the TO_DATE function with the YY datetime format element,
then the year returned always has the same first 2 digits as the
current year. If you use the RR datetime format element instead, then
the century of the return value varies according to the specified
two-digit year and the last two digits of the current year.
That is:
If the specified two-digit year is 00 to 49, then
If the last two digits of the current year are 00 to 49, then the
returned year has the same first two digits as the current year.
If the last two digits of the current year are 50 to 99, then the
first 2 digits of the returned year are 1 greater than the first 2
digits of the current year.
If the specified two-digit year is 50 to 99, then
If the last two digits of the current year are 00 to 49, then the
first 2 digits of the returned year are 1 less than the first 2 digits
of the current year.
If the last two digits of the current year are 50 to 99, then the
returned year has the same first two digits as the current year.

Related

Convert to datetime to specified format

I have been searching around for a while now, but I can't seem to find the answer to this small problem.
How to convert string 08-JUL-06 to datetime 08/07/1906? I've tried with code like the following:
select to_char(to_date('08-jul-06', 'dd-mon-rr'), 'dd/mm/yyyy') result from dual;
However, the result shows wrong: to be 08/07/2006? How do I solve the problem?
RR format is not suitable for this(*). How would Oracle know that you meant 1900s not 2000s? You know it because you know the context in which they occur. I suggest converting it to text and add 19 in front of the year yourself, like:
select to_date('19'||to_char(to_date('08-jul-06', 'dd-mon-yy'), 'yymmdd'),'yyyymmdd') result
from dual;
It is now a date, you can view it in the format you mentioned using to_char(...'dd-mon-yyyy'); or it might readily display like that if your Oracle installation date-format is that.
(*) If the specified two-digit year is 00 to 49, then
If the last two digits of the current year are 00 to 49, then the returned year has the same first two digits as the current year.
If the last two digits of the current year are 50 to 99, then the first 2 digits of the returned year are 1 greater than the first 2 digits of the current year.
If the specified two-digit year is 50 to 99, then
If the last two digits of the current year are 00 to 49, then the first 2 digits of the returned year are 1 less than the first 2 digits of the current year.
If the last two digits of the current year are 50 to 99, then the returned year has the same first two digits as the current year.
How to convert string 08-JUL-06 to datetime 08/07/1906?
You cannot, Oracle has two format models for handling two-digit years: YY and RR.
YY will assume the century is the current century.
RR will assume the century is:
The previous century if the specified year is 50-99 and the current year is 0-49
The current century if the specified year is 50-99 and the current year is 50-99
The current century if the specified year is 0-49 and the current year is 0-49
The next century if the specified year is 0-49 and the current year is 50-99
In none of these options will 06 assume that the full 4-digit year is 1906.
What you need to do is use a 4-digit year:
SELECT TO_CHAR(DATE '1906-07-08', 'dd/mm/yyyy') AS result FROM DUAL;
or, change your string to insert the century:
SELECT TO_CHAR(
TO_DATE(
SUBSTR(value, 1, 7) || '19' || SUBSTR(value, 8),
'DD-MON-YYYY',
'NLS_DATE_LANGUAGE=English'
),
'dd/mm/yyyy'
) AS result
FROM (SELECT '08-JUL-06' AS value FROM DUAL);
Which both output:
RESULT
08/07/1906
db<>fiddle here

AWS Athena (Trino SQL) Convert birthdate string (mm/dd/yy) to date -- need twentieth century

AWS Athena (Trino) Convert birthdate string (mm/dd/yy) to date -- need twentieth century
I have found similar questions, but they either aren't specific to Athena, or to this two-digit to date format for a birthdate (e.g. 56 should map to 1956)
An example of similar question (this one is 4-year date is):
Amazon Athena Convert String to Date
For example, cast( date_parse(trim("date of birth"),'%m/%d/%Y') as date ) as our_date_of_birth gives the laughable: 0094-01-04 instead of a date in 1994
However, if I use:
cast( date_parse(trim("date of birth"),'%m/%d/%y') as date ) as our_date_of_birth,
it sometimes gives me correct date, but sometimes something like: 2062-07-31 instead of 1962
Finally, just plain:
cast( trim("date of birth") as date ) as our_date_of_birth
gives an error: INVALID_CAST_ARGUMENT: Value cannot be cast to date: 10/11/78
Is there a way to get twentieth century birthdates from these casts in Athena Trino?
Obviously there would be edge cases such as 01/01/20 which could map to either 1920 or 2020, but dates like 01/01/50 should definitely map to 1950.
Sample data and outputs:
01/01/56 -- output would be 1956-01-01 as date
01/01/08 -- output would be 2008-01-01 as date
01/01/21 -- output would be 2021-01-01 as date (* some would want 1921 here)
07/01/21 -- output would be 1921-07-01 as date (since as of posting 07/01/2021 would be in future)
**The outuput format isn't crucial, it could be 01/01/1956, just so it is a true 'date' in Athena Trino.**
One way would be to subtract 100 years whenever the parsed date is in the future. For example:
select case when
parse_datetime(birthdate, 'MM/dd/yy') > current_timestamp then
parse_datetime(birthdate, 'MM/dd/yy') - interval '100' year
else parse_datetime(birthdate, 'MM/dd/yy')
end as birthdate
Note that this would work only until the next century.
The parse_datetime function returns a timestamp object, see the docs: https://prestodb.io/docs/current/functions/datetime.html
parse_datetime uses java's DateFormat conventions. From the docs:
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the SimpleDateFormat instance is created.

Convert week of the year to date in oracle sql

How can I get a date using the week of the year in Oracle SQL?
I need to search for entries created after the beginning of the current week. Currently, I get the week of the year by doing select to_char(sysdate,'WW') from dual;, but then I can't do
select * from table where date > to_date(to_char(sysdate,'WW'), 'WW') because I get
ORA-01820: format code cannot appear in date input format
01820. 00000 - "format code cannot appear in date input format"
*Cause:
*Action:
You don't need to convert to a string and back, you can use truncate:
select * from table where date > trunc(sysdate,'WW')
Read more about the trunc() function and how the format model is applied.
Notice that WW gives you the same day as the first day of the year, so right now that would give 2020-09-02, which is a Wednesday - possibly not what you'd expect. It depends on your requirements of course, but you might want to work with IW which always starts from Monday, and would give 2020-09-07. If you have a different start day you can add or subtract a day, e.g. if your week starts on Sunday.
According to ORA-doc:
ORA-01820: format code cannot appear in date input format
Cause: A date specification contained an invalid format code. Only the following may > be specified when entering a date: year, month, day, hours, minutes, seconds, Julian day, > A.M./P.M. and B.C./A.D.
Action: Remove the invalid format code from the date specification.
You can't pass the weeknum to to_date() function. What you can do is e.g., the following
select * from table where date > (next_day(trunc(sysdate), 'SUNDAY') - 7)
Basically, next_day returns first date that meets specified weekday. Let's assume it's Monday 2020-09-07, next_day will return you the closest SUNDAY in the future, that is 2020-09-13, so you need to substract 7 to get date of the current week beginning. You can read more about it here

Oracle date conversion outputs 2000s instead of required 1990s

During execution of below query, the output is 2090.
select to_char(to_date('10-OCT-90', 'DD-MON-YY'), 'YYYY') from dual;
Required output is 1990, the date in the snippet is Birth Date.
EDIT:
The input date is fetched from a table, so the date is in DD-MON-YY format.
For alternative resolving the double-digit years in strings, Oracle has the RR format element. Thus, your query would be
select to_char(to_date('10-OCT-90', 'DD-MON-RR'), 'YYYY') from dual;
From the referenced Oracle doc:
The RR datetime format element is similar to the YY datetime format element, but it provides additional flexibility for storing date values in other centuries. The RR datetime format element lets you store 20th century dates in the 21st century by specifying only the last two digits of the year.
Use RR instead of YY. See here: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements004.htm#SQLRF00215
Try to use RR like this:
select to_char(to_date('10-OCT-90', 'DD-MON-RR'), 'YYYY') from dual;
SQL FIDDLE DEMO
Also note that you should store the dates in YYYY format as it will be confusing to make the correct assumption as to the birth year is in 2000 or 1900 or 1800 or... ;)
The Oracle docs says:
YY allows you to retrieve just two digits of a year, for example, the
99 in 1999. The other digits (19) are automatically assigned to the
current century. RR converts two-digit years into four-digit years by
rounding.
50-99 are stored as 1950-1999, and dates ending in 00-49 are stored as
2000-2049. RRRR accepts a four-digit input (although not required),
and converts two-digit dates as RR does. YYYY accepts 4-digit inputs
butdoesn't do any date converting
I had the same issue for my Date column (DOB) if DOB is 27-08-1947. I use below conversion format to get correct year to calculate age.
TO_DATE(TO_CHAR(DOB,'DD-MON-YYYY'), 'DD-MON-YYYY')
TO_DATE(TO_CHAR(DOB,'DD-MM-YYYY'), 'DD-MM-YYYY')
SELECT TRUNC(SYSDATE) TODAY,
TO_DATE(BIRTH_DATE,'DD-MON-RR') DOB,
BIRTH_DATE
FROM TM_DM_CLIENT
WHERE CLIENT_NO IN ('22943179')
output
Today DOB BIRTH_DATE
10/1/2019 1/1/2041 1/1/1941

How to extract week number in sql

I have a transdate column of varchar2 type which has the following entrees
01/02/2012
01/03/2012
etc.
I converted it in to date format in another column using to_date function. This is the format i got.
01-JAN-2012
03-APR-2012
When I'm trying to extract the weekno, i'm getting all null values.
select to_char(to_date(TRANSDATE), 'w') as weekno from tablename.
null
null
How to get weekno from date in the above format?
After converting your varchar2 date to a true date datatype, then convert back to varchar2 with the desired mask:
to_char(to_date('01/02/2012','MM/DD/YYYY'),'WW')
If you want the week number in a number datatype, you can wrap the statement in to_number():
to_number(to_char(to_date('01/02/2012','MM/DD/YYYY'),'WW'))
However, you have several week number options to consider:
WW Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.
W Week of month (1-5) where week 1 starts on the first day of the month and ends on the seventh.
IW Week of year (1-52 or 1-53) based on the ISO standard.
Try to replace 'w' for 'iw'.
For example:
SELECT to_char(to_date(TRANSDATE, 'dd-mm-yyyy'), 'iw') as weeknumber from YOUR_TABLE;
Select last_name, round (sysdate-hire_date)/7,0) as tuner
from employees
Where department_id = 90
order by last_name;
Use 'dd-mon-yyyy' if you are using the 2nd date format specified in your answer. Ex:
to_date(<column name>,'dd-mon-yyyy')