Extract month and year from date in oracle - sql

what is the query for extract month and year from full date.
my data is like this: 1/29/2008
I tried this query:
select ID_NO, CHECKED_DATE, to_date(TO_CHAR(CHECKED_DATE, 'MON-YYYY'), 'MON-YYYY') AS A
from Doctor_Checkup;
but It will give output: 1/1/2008
Expected output: 1-2008

If the field is already a date column, you can simply cast it to the format you want:
select ID_NO,CHECKED_DATE,ltrim(TO_CHAR(CHECKED_DATE,'mm-yyyy'),'0') AS A from Doctor_Checkup;
If it is a text column, you will need to cast to a date with format first:
select ID_NO,CHECKED_DATE,ltrim(TO_CHAR(TO_DATE(CHECKED_DATE,'dd/mm/yyyy'),'mm-yyyy'),'0') AS A from Doctor_Checkup;

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.
One thing to note is that a date always has the year, month, day, hour, minute and second components. Doing:
to_date(TO_CHAR(CHECKED_DATE, 'MON-YYYY'), 'MON-YYYY')
Is effectively the same as doing:
TRUNC( Checked_Date, 'MM' )
and will still have a day, hour, minute and second component but will have been truncated to midnight of the first day of the month. The user interface may just be have its preferences set to not display the time component (but the date will still have one).
What you want to do is convert the date to a formatted string:
select ID_NO,
CHECKED_DATE,
TRIM( LEADING '0' FROM TO_CHAR( CHECKED_DATE, 'MM-YYYY') ) AS A
from Doctor_Checkup;
or
select ID_NO,
CHECKED_DATE,
EXTRACT( MONTH FROM CHECKED_DATE )
|| '-' || EXTRACT( YEAR FROM CHECKED_DATE ) AS A
from Doctor_Checkup;

You want a string representing month and year in the format [M]M-YYYY. Oracle's TO_CHAR only supports MM-YYYY, though, so you'd have to get rid of a leading zero if any.
Two solutions:
trim(leading '0' from to_char(checked_date, 'mm-yyyy'))
or
extract(month from checked_date) || '-' || extract(year from checked_date) from dual

To get 1-2008 format use the following format with trimming leading zeroes:
select ID_NO,CHECKED_DATE,ltrim(TO_CHAR(CHECKED_DATE,'MM-YYYY'),'0') AS A from Doctor_Checkup;

SELECT ID_NO, CHECKED_DATE FROM DOCTOR_CHECKUP EXTRACT(MONTH FROM CHECKED_DATE) IN (6) AND EXTRACT(YEAR FROM CHECKED_DATE) IN (2019);
6 MEANS THE MONTH AND 2019 IS THE YEAR

LTRIM(TO_CHAR(TO_DATE(<date_field>,'YYYYMMDD'),'YYYY-MM'),'09'))

Related

How to easily get year and month with leading zero in BigQuery?

I have a snapshot date in the following format: 2021-06-28 and I would like to have it like that: 202106. So the first four digits is year and next two is the month with leading zero. I tried this code:
concat(extract(year from snapshot_date), extract(month from snapshot_date))
but I have in return: 20216, without leading zero. How can I easily get it without CASE statement?
Try format_date:
select format_date("%Y%m", snapshot_date)
from mytable
Assuming snapshot_date is of date data type - you can use recently introduced Format clause for CAST as in below example
select cast(snapshot_date as string format 'YYYYMM')
from `project.dataset.table`
if "snapshot_date" is in date format, then this should work
select to_char(snapshot_date, 'yyyymm') from table_name
As a note, you can return the value as a number and just use multiplication:
(extract(year from snapshot_date) * 100 + extract(month from snapshot_date)) as yyyymm

SQL Query to get the first day of the month passed in the parameter of the current year

I want to get the first day and last day of the month passed in the parameter.
I tried to use the below query, but it is erroring out.
select LAST_DAY(to_date(to_char(('01'||:P_MONTH||'2020'),'DDMMYYYY'),'YYYYMM'))
FROM DUAL
I want to use this in a query
select * from
GL_CODE_TAB
where effective_start_date = LAST_DAY(to_date(to_char(('01'||:P_MONTH||'2020'),'DDMMYYYY'),'YYYYMMDD'))
and search the table GL_CODE_TAB for the first/last day of the month I pass, e.g. if I pass "May"
select * from
GL_CODE_TAB
where effective_start_date = LAST_DAY(to_date(to_char(('01'||'May'||'2020'),'DDMMYYYY'),'YYYYMMDD'))
which should do a search like
select * from
GL_CODE_TAB
where effective_start_date = '20200531'
Something is off in your logic. You don't need to convert strings to strings. So, I am thinking:
SELECT LAST_DAY(TO_DATE('01' || :P_MONTH || '2020', 'DDMMYYYY'))
FROM DUAL
The pattern MM is looking for a numerical month. (You also have the format pattern 'DDMMYYYY' twice in your query; I am not sure why.)
It so happens that that Oracle defaults the year to the current year and the day of the month to the current month. So, you don't even need to mess around with strings:
SELECT LAST_DAY(TO_DATE(:P_MONTH , 'MM'))
FROM DUAL;
The above assumes a numerical value for your parameter. If you want to handle a string, then:
SELECT LAST_DAY(TO_DATE('01' || :P_MONTH || '2020', 'DDMONYYYY'))
FROM DUAL
Or:
SELECT LAST_DAY(TO_DATE(:P_MONTH , 'MON'))
FROM DUAL;
If you want to pass the full month name, use MONTH instead of MON.
The inner call to TO_CHAR() is the problem. Just use TO_DATE() as follows, with the proper format specifier as second argument:
SELECT LAST_DAY(TO_DATE('01 ' || :P_MONTH || ' 2020'),'DD MONTH YYYY'))
FROM DUAL
It is unclear whether the parameter is a full or abbreviated month name (May is ambiguous in that regard). I assumed it's the former. If that's a short name, then use 'DD MON YYYY' instead.
In your query:
SELECT *
FROM GL_CODE_TAB
WHERE effective_start_date = LAST_DAY(TO_DATE('01 ' || :P_MONTH || ' 2020'),'DD MONTH YYYY'))
If you need 20200531 in the where clause, I think you want
select to_char(last_day(to_date(('01'||'May'||'2020'),'DDMMYYYY')), 'YYYYMMDD')
from dual;

oracle compare a date with the current date

I have to convert a column to a date and then compare the month of the column with the current month.
The column looks like this :
Date
0117
0217
0317
..
I know how to convert it but cant compare it.
select date,to_date(date, 'mmyy')
from table
where ????
any ideas?
You can convert the value to a date using to_date():
select to_date(mmyy, 'MMYY')
from t;
Note that I renamed the column mmyy to clarify what it contains.
This returns the first day of the month.
The result of to_date() can then be compared to the current date. For instance, to match the first of date of the month:
where to_date(mmyy, 'MMYY') = trunc(sysdate)
If you want to match everything in the month, just use an appropriate comparison:
where to_char(to_date(mmyy, 'MMYY'), 'YYYY-MM') = to_char(sysdate, 'YYYY-MM')
or, more simply:
where mmyy = to_char(sysdate, 'MMYY')
You can convert the current date to a string and use string comparisons (which would allow you to use an index on your column):
SELECT *
FROM your_table
WHERE your_date_column = TO_CHAR( SYSDATE, 'MMYY' )
or you can convert the column to a date and compare it (which would not use an index on your column but could use a function-based index, if you created one):
SELECT *
FROM your_table
WHERE TO_DATE( your_date_column, 'MMYY' ) = TRUNC( SYSDATE, 'MM' )

Oracle SQL Create Date from Parts

I have two date fields in a database called "EFFECTIVE_DATE" and "POINT_DATE"
How do I create a new date field, where the date is made up from the year of "EFFECTIVE_DATE", the month of "POINT_DATE" and the day of "POINT_DATE" ?
I would normally use Datefromparts, but this is an Oracle Database not Microsoft
Kind Regards
Here's an approach using ADD_MONTHS and EXTRACT(YEAR FROM ....). You simply add or subtract the needed number of months (always a multiple of 12, since you are only changing the year). Unlike the TO_CHAR / TO_DATE solutions, this approach handles leap days (Feb. 29). On the other hand, be advised that changing the date from 28 Feb. 2003 to the year 2012 will change it to Feb. 29 (ADD_MONTHS changes the last day of a month to the last day of the resulting month).
with
inputs as (
select date '2013-03-22' as effective_date,
date '2017-08-14' as point_date
from dual
)
-- end of TEST data (do not include in the solution!)
select effective_date, point_date,
add_months(point_date, 12 * ( extract (year from effective_date) -
extract (year from point_date) )
) as mixed_date
from inputs;
EFFECTIVE_DATE POINT_DATE MIXED_DATE
-------------- ---------- ----------
03/22/2013 08/14/2017 08/14/2013
Hmmm . . . this produces a nice string in the YYYY-MM-DD format:
select to_char(effective_date, 'YYYY') || '-' || to_char(point_date, 'MM-DD')
And this parses it back to a date:
select to_date(to_char(effective_date, 'YYYY') || '-' || to_char(point_date, 'MM-DD'), 'YYYY-MM-DD')
Note: You might want to be careful about Feb 29th.
Assuming all coulmns are DATE data types, you can use this one
TO_DATE(TO_CHAR(EFFECTIVE_DATE, 'YYYY') || TO_CHAR(POINT_DATE, 'MMDD'), 'YYYYMMDD')
Be aware of leap years!

How to convert a sysdate month value to number in oracle?

Im trying to return the CARDS of my CARD table that will expire in the next month. But the problem is that the table has two columns to represent the card date. The columns are EXPIREDAY and EXPIREMONTH ,both are numbers. So when i do that query i get an error:
select * from CARD WHERE EXPIREDAY <= sysdate - interval '2' DAY;
//Oracle error: ORA-00932: inconsistent datatypes: expected NUMBER got DATE
Is there a way to convert the sysdate - interval '2' DAY as Number data type?
Thanks!
If you want to compare the values as strings you can use this to convert the SYSDATE
SELECT TO_CHAR(sysdate, 'MM') || TO_CHAR(sysdate, 'DD') MONTH_NUM FROM DUAL
-- gives you "0922"
and this for your numeric columns which will pad with leading zeros if you only have a single digit
SELECT TO_CHAR(9, 'FM00') || TO_CHAR(22, 'FM00') MONTH_NUM FROM DUAL
-- also gives you "0922"
If you have control over the table schema it would be best practise to store both the DAY and MONTH values in a single numeric field, so that 9-SEP would be stored in this column as the numeric value 0922 where the month is first so that the natural ordering is used.
A simple and not necessarily very efficient approach is to convert the day and month values into an actual date, using to_date(), and then compare that with your target date range:
select * from card
where to_date(lpad(expireday, 2, '0')
||'/'|| lpad(expiremonth, 2, '0'), 'DD/MM')
between sysdate and add_months(sysdate, 1);
Which appears to work. But this will have problems if the dates span the end of the year. Because your table doesn't specify the year, you either have to work one out, or allow to_date to default it to the current year. And if you let it default then it won't work. For example, if you have values for December and January in your table, and run this query in December, then the January dates will be seen as January 2014, and won't be counted as being in the next month. So you'll need to do more to pick the right year.
This treats any month numbers before the current one as being next year, which may be good enough for you as you only have a one-month window:
select * from card
where to_date(lpad(expireday, 2, '0')
||'/'|| lpad(expiremonth, 2, '0')
||'/'|| (extract(year from sysdate) +
case when expiremonth < extract(month from sysdate) then 1 else 0 end),
'DD/MM/YYYY')
between sysdate and add_months(sysdate, 1);
SQL Fiddle using a date range from December to January.
And you can see the ways the two columns are being combined to form a date in this Fiddle.
As so often, the moral is... store things as the right data type. Store dates as dates, not as string or numbers.
Im trying to return the CARDS of my CARD table that will expire in the next month. But the problem is that the table has two columns to represent the card date.
Assuming:
you are using floating months (say: from 23 dec. to 23 jan.) and
your table somehow only contains one (floating ?) year of data
Why can't you use simple arithmetics? Like that:
-- some constant definitions for testing purpose
with cst as (
select EXTRACT(DAY from TO_DATE('23/12','DD/MM')) as theDay,
EXTRACT(MONTH from TO_DATE('23/12','DD/MM')) as theMonth
from dual)
-- the actual query
select card.* from card,cst
where (expiremonth = theMonth AND expireday > theDay)
or (expiremonth = 1+MOD(theMonth,12) AND expireday <= theDay);
-- ^^^^^^^^^^^^^^^^^^
-- map [01 .. 12] to [02 .. 12, 01] (i.e.: next month)
This will simply select all "pseudo-dates" from tomorrow to the end of the month, as well as any one before (and including) the current day# next month.
See this example.
For something a little bit more generic, but probably more efficient than converting all your values TO_DATE, you might want to try that:
-- the calendar is the key part of the query (see below)
with calendar as (
select extract(month from sysdate + level) as theMonth,
extract(day from sysdate + level) as theDay
from DUAL connect by ROWNUM <= 8)
-- ^
-- adjust to the right number of days you are looking for
select card.* from card join calendar
on expiremonth = theMonth and expireDay = theDay
The idea here is to simply build a calendar with all the upcoming days and then join your data table on that calendar. See an example here.
Try using to_char(sysdate - interval '2' DAY,'ddmmyyyy') to convert to character type. The date format('ddmmyyyy') will depend of the value of expiredate