Reputation: 115
I am trying to get count of distinct months between two dates. However, I am getting a missing right parenthesis error. As with many of us I like using dual table on the fly.
Here is the query. Can you please advise what I am doing wrong?
SELECT
COUNT(DISTINCT(TRUNC BETWEEN TO_DATE('2019-08-01','YYYY-MM-DD') AND TO_DATE('2020-07-07','YYYY-MM-DD'),'MM'))
FROM dual
Upvotes: 0
Views: 648
Reputation: 1
months_between may not be solution for all scenarios; example:
SELECT MONTHS_BETWEEN (TO_DATE('2021-12-20','YYYY-MM-DD'),TO_DATE('2022-01-05','YYYY-MM-DD')) FROM dual will result is 0.5 months; but actually both dec and jan are used in query and expected result may 2.
So using above example of with function will provide correct result no matter.
Upvotes: 0
Reputation: 191275
Counting isn't the right tool for this really; your trunc()
is missing its opening parenthesis, but BETWEEN
is a condition not a function, so that is also wrong.
Oracle has the months_between()
function to do this; it will give a fractional value, so you can use floor()
to get the number of complete months, or ceil()
to get the number of partial months:
select
months_between (date '2020-07-07', date '2019-08-01') as result1,
floor(months_between (date '2020-07-07', date '2019-08-01')) as result2,
ceil(months_between (date '2020-07-07', date '2019-08-01')) as result3
from dual;
RESULT1 RESULT2 RESULT3
---------- ---------- ----------
11.1935484 11 12
If you wanted to list the months then you could use a hierarchcal query or recursive subquery factoring, e.g.:
with rcte (this_month, last_month) as (
select trunc(date '2019-08-01', 'MM'), trunc(date '2020-07-07', 'MM')
from dual
union all
select r.this_month + interval '1' month, r.last_month
from rcte r
where r.this_month < r.last_month
)
select this_month
from rcte
order by this_month;
THIS_MONTH
----------
2019-08-01
2019-09-01
2019-10-01
...
2020-06-01
2020-07-01
and count those instead:
with rcte (this_month, last_month) as (
select trunc(date '2019-08-01', 'MM'), trunc(date '2020-07-07', 'MM')
from dual
union all
select r.this_month + interval '1' month, r.last_month
from rcte r
where r.this_month < r.last_month
)
select count(this_month) as result
from rcte;
RESULT
------
12
but that's more work than you need to do if you only want that number.
Upvotes: 1
Reputation: 35900
Your approach is incorrect and It is better to use MONTHS_BETWEEN
as it takes care of everything i.e. different number of days in the month and etc.
You can use MONTHS_BETWEEN
as follows:
SELECT
MONTHS_BETWEEN (TO_DATE('2020-07-07','YYYY-MM-DD'),TO_DATE('2019-08-01','YYYY-MM-DD'))
FROM dual
Upvotes: 1