Reputation: 43
I want to ask you how can I get count of specific date (DD-MON) from date range (DD-MON-YY) from Oracle SQL? This is what I have:
MEMBERS INSTALL_D DOB SYSDATE
6934109 22-FEB-12 18-NOV 09-JAN-17
6934109 22-FEB-12 13-JUN 09-JAN-17
6934109 22-FEB-12 12-AUG 09-JAN-17
6934109 22-FEB-12 24-OCT 09-JAN-17
6934109 22-FEB-12 04-FEB 09-JAN-17
I want count DOB from range of dates INSTALL_D and SYSDATE. Let's say that the
and the last one is only 4 times.
so, the result should be like:
MEMBERS INSTALL_D DOB SYSDATE COUNT(DOB)
6934109 22-FEB-12 18-NOV 09-JAN-17 5
6934109 22-FEB-12 13-JUN 09-JAN-17 5
6934109 22-FEB-12 12-AUG 09-JAN-17 5
6934109 22-FEB-12 24-OCT 09-JAN-17 5
6934109 22-FEB-12 04-FEB 09-JAN-17 4
I tried used MONTHS_BETWEEN function but this is not what I want to get.
EDIT:
I will be more specific. I used this query to get the first table above:
select B0022HOME_NO as Members,
B0022INSTALLDATE as INSTALL_DATE,
to_char(to_date (encryption.decrypt(a.B0031MEMDATEOFBIRT),'DD-MON-YYYY'),'DD-MON')as DOB,
SYSDATE
from BT0022, BT0031 a
where B0022HOME_NO=a.B003101HOME_NO and BT0022.B0022HOME_NO=6934109;
INSTALL_D
is day of instalation, which is in this example 22-FEB-12
DOB
is birthday of member. Only day and month (DD-MON)
SYSDATE
is for actual date.
Let's say, if the sysdate would be 18-NOV-12 and INSTALL_D is 22-FEB-12 and DOB of member is 18-NOV, that's mean that the DOB is occur once in this range of date.
In example: INSTALL_D 22-FEB-12 and SYSDATE 09-JAN-17 is DOB of 18-NOV occur 5 times, but if the SYSDATE will be 18-NOV-17, it will be 6 times. And that's it what I asked you about count(DOB) in date range.
Thanks in advance
Upvotes: 1
Views: 1451
Reputation: 23588
Here's another way that will hopefully work with dob's that occur on leap years:
(N.b. I have assumed all your dates are stored as DATEs, meaning that your dob column has years. If that isn't the case, then a) why aren't you storing the year with the dob? and b) you'll have to update my query to convert the string into a suitable format for the comparison)
WITH sample_data AS (SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('18/11/1969', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('13/06/1991', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('12/08/1982', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('24/10/1963', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('04/02/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934110 members, to_date('28/02/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934110 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('01/03/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('12/01/1957', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('02/01/1980', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934112 members, to_date('01/03/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL
SELECT 6934112 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual)
SELECT members,
install_d,
dob,
SYSDATE,
date_of_first_year,
date_of_latest_year,
months_between(date_of_latest_year, date_of_first_year)/12 + 1 count_birthdays
FROM (SELECT members,
install_d,
dob,
SYSDATE,
CASE WHEN to_char(dob, 'mmdd') < to_char(install_d, 'mmdd') THEN
trunc(add_months(install_d, 12), 'yyyy')
ELSE trunc(install_d, 'yyyy')
END date_of_first_year,
CASE WHEN to_char(dob, 'mmdd') <= to_char(SYSDATE, 'mmdd') THEN
trunc(SYSDATE, 'yyyy')
ELSE add_months(trunc(SYSDATE, 'yyyy'), -12)
END date_of_latest_year
FROM sample_data);
MEMBERS INSTALL_D DOB SYSDATE DATE_OF_FIRST_YEAR DATE_OF_LATEST_YEAR COUNT_BIRTHDAYS
---------- ----------- ----------- ----------- ------------------ ------------------- ---------------
6934109 22/02/2012 18/11/1969 09/01/2017 01/01/2012 01/01/2016 5
6934109 22/02/2012 13/06/1991 09/01/2017 01/01/2012 01/01/2016 5
6934109 22/02/2012 12/08/1982 09/01/2017 01/01/2012 01/01/2016 5
6934109 22/02/2012 24/10/1963 09/01/2017 01/01/2012 01/01/2016 5
6934109 22/02/2012 04/02/1975 09/01/2017 01/01/2013 01/01/2016 4
6934110 28/02/2011 29/02/1976 09/01/2017 01/01/2011 01/01/2016 6
6934110 29/02/2012 01/03/1975 09/01/2017 01/01/2012 01/01/2016 5
6934111 01/01/2017 12/01/1957 09/01/2017 01/01/2017 01/01/2016 0
6934111 01/01/2017 02/01/1980 09/01/2017 01/01/2017 01/01/2017 1
6934112 01/03/2011 29/02/1976 09/01/2017 01/01/2012 01/01/2016 5
6934112 29/02/2012 29/02/1976 09/01/2017 01/01/2012 01/01/2016 5
The only fly in the ointment occurs if you want a dob of 29th Feb to match to 1st of March on non-leap years.
My query above doesn't have that logic in it, but you could always add in a check to compare the last day of February in the install_d and sysdate years, and if it's 28th, then change a dob of '29/02' to '01/03' before doing that comparison. (I.e. compare install_d of 29/02/2012 with dob = 29/02 as 2012 is a leap year. You don't need to compare the sysdate, since 0301 >= 0229 and 0228 < 0229, regardess of whether the sysdate is a leap year or not.)
Upvotes: 1
Reputation: 1815
Try this: (group by should work)
SELECT MEMBERS,INSTALL_D,DOB,SYSDATE,Count(DOB) FROM table_name GROUP BY DOB ,MEMBERS,INSTALL_D ,SYSDATE
Upvotes: 0
Reputation: 827
You could group by date segments, it's not the prettiest thing but will work. e.g.
GROUP BY CAST(DATEPART(mm, dob) AS VARCHAR(2)) + '-' + CAST(DATEPART(yyyy, dob) AS VARCHAR(4))
you could also place that in the select statement
Upvotes: 0