How to extract month number from date in Oracle - sql

I have ID_BB_SECURITY column where the date value is stored in this column for example '20190801'.
I want to get month number from this field for example for August date i want to get 8.
I tried below query but it throws an error 'literal does not match':
select to_number(to_date(ID_BB_SECURITY),'mm') from BT_EXPORT
I am not sure if i have to ignore null values so as to avoid the error

If the value is a number or string then you can convert it to a date with an appropriate mask - which is what you are missing, and what is causing the error you are getting (as it's using your session's NLS_DATE_FORMAT setting, which apparently does not match the format of the data; but which you should not rely on anyway, as #MTO said in comments):
to_date(ID_BB_SECURITY, 'YYYYMMDD')
and then extract the month number from that:
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
Or you could just use a substring:
select to_number(substr(ID_BB_SECURITY, 5, 2)) from BT_EXPORT;
Those assume a fixed consistent format, which is always a risky assumption when using the wrong data type. Ans if it's a number they are doing an implicit conversion from number to string, which you could turn into an explicit conversion for greater clarity.
If it's already a date - as it should be, of course - then you don't need the conversion:
select extract(month from ID_BB_SECURITY) from BT_EXPORT

If you have a number, you can use arithmetic to extract the month:
select mod(floor(20190801 / 100), 100)
from dual;

You could try converting the number date to a string, and then extracting the 5th and 6th characters:
SELECT
SUBSTR(TO_CHAR(ID_BB_SECURITY), 5, 2) AS mm
FROM BT_EXPORT;
But, it would be much better for you to use a proper date column. Then, you could use a less draconian method such as:
SELECT
TO_CHAR(ID_BB_SECURITY, 'mm') AS mm -- assuming date
FROM BT_EXPORT;

select to_number(to_char(to_date('20190801', 'yyyymmdd'), 'mm')) from dual

Try this one
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
This one convert number to date then extract month.

also
select extract(month from to_date('20190801', 'yyyymmdd')) from dual

Your date column has the value stored in the following format "yyyymmdd" where
yyyy is the year
mm the month
dd the day
So in order to return the number value of the month (mm) we can do as follows:
1: first transform the value from a number to a date using
to_date(20190801,'yyyymmdd')
2: get month using to_date operator
to_char( to_date(20190801,'yyyymmdd'), 'mm')

Related

How do I extract the month from the Date column in SQL-postgres

I am trying to extract the month from the the Order_date column by using postgres SQL , and the format is required to come in the name of the month format ;for example, December.
When I applied the extract function , It gave me an error message saying that the date setting has to be changed.
Please advise how to extract the month from the mentioned column ?
The data has been enclosed
SELECT EXTRACT(MONTH FROM order_date::date)
FROm think_sales;
The error message :
[22008] ERROR: date/time field value out of range: "25/06/2021" Hint: Perhaps you need a different "datestyle" setting.
Data :
You may need to define your date format using the to_date function:
select to_char(to_date('25/06/2021', 'dd/mm/yyyy'), 'Month');
Output: June
In your case, you would use:
select to_char(to_date(order_date, 'dd/mm/yyyy'), 'Month');
This work for me:
SELECT EXTRACT(MONTH FROM TIMESTAMP '25/06/2021');
https://www.postgresqltutorial.com/postgresql-date-functions/postgresql-extract/
set date format to dmy (day - month - year )
SET datestyle = dmy;
This answer

fetch records between 'current date ' and next 5 days(future date) in oracle

Select * from dual where between to_date(date,'YYYY-MM-DD') = '2020-10-01'
and to_date(date,'YYYY-MM-DD') + 5
this is correct way to write query?
1.format of date is varchar2
2.required data between current date and next 5 days
3.first needs to convert into date format.
4. next 5 should be +5 in current day
You probably meant to write:
where to_date(mydate, 'yyyy-mm-dd') between trunc(sysdate)
and trunc(sysdate) + 5
Rationale:
date is a reserved word; I assume that's not the actual name of your column, so I used something else; if that's the real name, then you need to surround it with double quotes ("date", or "DATE", or else, depending on how it was initially defined)
mydate is a string so you need to turn it to a date: for this, you can use to_date()
you then compare it to the current date, without the time portion : trunc(sysdate), and the same date 5 days later
Note, however, that this would be more efficiently expressed as follows:
where mydate between to_char(trunc(sysdate), 'yyyy-mm-dd')
and to_char(trunc(sysdate + 5), 'yyyy-mm-dd')
This avoids the date conversion on the string column, and instead converts the interval bounds. Here, string comparison is possible, because the format of the string you are storing allows it (it it was stored as dd-mm-yyyy' for example, this would not be possible).
Let me, however, strongly suggest to store your dates as dates rather than string. You should always use the proper datatype, for many reason, such as data integrity and efficency.

How to compare 2 converted dates in sql

I'm trying to exclude results in my query that start in the same month between two columns. For example, I need to exclude benefits1 that start in the same month as benefits2. Format for benefit1_start_date and benefit2_start_date is: YYYYMMDD.
This is what I have so far:
where (benefit1_start_date = (to_char(sysdate, 'YYYYMM') || '0122')) <>
(benefit2_start_date = (to_char(sysdate, 'YYYYMM') || '0122'));
If anyone could put me in the right direction, I'd greatly appreciate it!
Convert your numeric dates to text, and then compare the year and month substrings:
WHERE
SUBSTR(TO_CHAR(benefits1_start_date), 1, 6) <> SUBSTR(TO_CHAR(benefits2_start_date), 1, 6)
Note that storing your dates as numbers like this is atypical, and you might want to consider storing them as dates. If you don't have a day component, you could just use the first as a placeholder.
As I understand it, you want to eliminate records where your 2 columns benefits1_start_date and benefits2_start_date are in the same month, and both have a format of YYYYMMDD.
Are they stored as strings? If so, all you need to do is compare the first 6 characters (if you need to consider yr + month), or just the 5+6th characters if you want to check just the month without the year.
Year + Month:
SUBSTR(benefits1_start_date,1,6) <> SUBSTR(benefits2_start_date,1,6)
Just month:
SUBSTR(benefits1_start_date,5,2) <> SUBSTR(benefits2_start_date,5,2)
If they're not stored as strings but as dates, then you can TRUNC the date to month and compare (for yr + month), or convert the date to MM string via to_char and compare if you just want to check the month.
Hope this helps.
I suggest you to use BETWEEN clause. Converting LEFT side operand to string by function and then making comparison can have severe performance impacts.
if you convert indexed table.dateColumn to string by to_char(table.dateColumn), oracle cannot use defined index on column anymore.
Your desired query:
where to_char(benefit1_start_date, 'YYYYMM') != to_char(benefit2_start_date, 'YYYYMM')
but
select * from table1
where months_between(benefit1_start_date, benefit2_start_date) not between -1 and 1
would be what you are looking for. (no performance impact)

To get all the dates in a format dd/mm/yyyy. I have a date field in the format yyyymmdd

In my DB, there is a date field in the format yyyymmdd.
I have to get all the dates in the format dd-mm-yyyy for that particlar date.
ex:
Date
20170130
20170228
20170325
for the above dates, I need the output in the below format with the dates and day of the particular dates
date day
30-01-2017 tuesday
28-02-2017 tuesday
25-03-2017 saturday
If the column is a string, then it can hold invalid date values such as February 31, one way to avoid this is by a small function such as this:
create or replace
function my_to_date( p_str in varchar2 ) return date
is
begin
return to_date( p_str );
exception
when others then
return null;
end;
\\
select to_char(my_to_date('20170231'),'DD-MM-YYYY Day')
from dual
\\
Demo
Try below:
Select to_char(yrdate, 'dd-mm-yyyy'), to_char(yrdate, 'D') from yrtable
It sounds like your dates aren't actually DATE fields but some kind of CHAR field? The best option would be to convert to DATE and then convert back to CHAR:
SELECT TO_CHAR(TO_DATE(mydate, 'YYYYMMDD'), 'DD-MM-YYYY Day')
FROM mytable;
This uses the YYYYMMDD mask to convert your string into a date, then uses the mask DD-MM-YYYY Day to convert it back into a string. Use day if you want the day name in lowercase (as in your OP).
#user2778168 answer will give you the results you want. But why?
Your database does not have dates stored in yyyymmdd format or any other date format for at mater, unless it's defined with a character type definition. Oracle stores all dates in a single internal structure, and with only slight variations timestamps are the same. The format used only tells Oracle how to display the value or to convert a string to a date. Unless a specific format is specified Oracle uses the NLS_DATE_FORMAT for this determination. See here and scan down to "Datetime Format Models" for format specifications.
To see this run the following:
select value
from nls_session_parameters
where parameter = 'NLS_DATE_FORMAT';
Select yrdate default_format
, to_char(yrdate, 'dd-mm-yyyy') specified_format
, dump(yrdate) unformated
from yrtable;
alter session set nls_date_format = 'Month dd,yyyy';
Rerun the above queries.
It seems you hold date column(date1) in character format. Suppose you have a table named days:
SQL> desc days
date1 varchar2(10)
then,
we should convert it into date, and then into char format, with aliases in quotation marks to provide lowercase aliases as you wanted.
perhaps your database's date language is non-english like mine(turkish), then you need to convert it to english.
lastly, it'a appropriate to order the results according to converted date, seen from your output. So we can use the following SQL :
select to_char(to_date(date1,'yyyymmdd'),'dd-mm-yyyy') "date",
to_char(to_date(date1,'yyyymmdd'),'day','nls_date_language=english') "day"
from days
order by to_date(date1,'yyyymmdd');
D e m o

Compare YYYYMM with date range

I have a question on how to compare YYYYMM in Oracle SQL.
graduation_date is saved in string format like '200212'. I want to query rows with graduation_date from Jan 2007 to Jan 2010.
Here is my query:
select ids,
from table
where to_date(substr(graduation_date,1,6),'YYYYMM' between 'Jan-2007'and 'Jan-2010'
I got error
ORA-01858:a non-numeric character was found where a numeric was
expected
Can anyone can help figure this out? Many thanks!
I found a way to compare. Since the graduation_date is saved as vchar2 format like '20021200'.Default value is '00000000'. ONLY Year & Month is saved in Graduation_date. Here is my query:
select ids,
from table
where graduation_date between '20070100'and '20100100'
I tired some other ways advised but got ORA-01843: not a valid month error
select ids,
from table
where to_date(substr(graduation_date,1,6),'YYYYMM' between 'Jan-2007'and 'Jan-2010'
Thank you guys but just wondering why I can't use to_date to compare in this scenario?
Remove the comma after ids... Need a closing bracket after YYYYMM, is graduation_date of type char/varchar? If not then you can't do substr... Finally do to_date('200701', 'YYYYMM') and to other date also...
In Addition to delete comma here: select ids, and to add bracket after 'YYYYMM' here: To_date(substr(graduation_date,1,6),'YYYYMM' you also need to know:
You are seeing the dates in the format which is set in your NLS settings. Even after conversion you letting your NLS to show in already set format, in your case it's seems like MM/DD/YYYY, check by:
SELECT VALUE FROM nls_session_parameters WHERE parameter = NLS_DATE_FORMAT';
if you want to select date in your special format then after to_date function also use to_char function, like (if your data is in that graduation_date column like YYYYMM then no need to use substr function, else use as below):
SELECT to_char (to_date (SUBSTR (graduation_date, 1, 6), 'YYYYMM'), 'YYYYMM') FROM table;
So, if you want to select your data, then use below script (if your data is in that graduation_date column like YYYYMM then no need to use substr function, else use as below):
SELECT ids
FROM table
WHERE to_date (SUBSTR (graduation_date, 1, 6), 'YYYYMM')
BETWEEN to_date ('200701', 'YYYYMM') AND to_date ('201001', 'YYYYMM');
I don't suggest to use 'Jan-2012' (even if you convert by to_char function) with BETWEEN cause it will compare bytes of letter, not the month, so it's possible to get also June or July for each year if you use like this (and data only for Jan, not all months between them):
WHERE to_char (to_date (SUBSTR (graduation_date, 1, 6), 'YYYYMM'), 'Mon-YYYY')
BETWEEN 'Jan-2007' AND 'Jan-2010';
result something like this:
Jan-2007
Jun-2007
Jul-2007
Jan-2010 ...