Hi, I have this query:
SELECT Count(tblpeople.PersonID) AS Total,
YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) AS YearsMember
FROM tblmembership INNER JOIN tblpeople ON tblmembership.PersonID = tblpeople.PersonID
WHERE
(
(
(
tblpeople.MemSTATUS = 'Back from VPM'
)
OR (
tblpeople.MemSTATUS = 'Sent To VPM 2'
)
OR (
tblpeople.MemSTATUS = 'Sent To VPM 1'
)
OR (
tblpeople.MemSTATUS = 'Back from VPM'
)
OR (tblpeople.MemSTATUS = 'Renewal')
OR (
tblpeople.MemSTATUS = 'Active Member'
)
)
)
GROUP BY YearsMember
HAVING YearsMember
ORDER BY YearsMember
It gets counts on years people have been a member.
What has me stumped is the boss wants it broken down by:
0 - 2
3 -5
6 - 10
11 - 20
20
So counts for each. I can not figure out how to do this, though I’m sure there’s a way!
I can just bring this into excel and manually group the counts, but wanted it done all in one shot.
Thanks
First of all, you can simply what you have a bit:
SELECT
Count(tblpeople.PersonID) AS Total,
YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) AS YearsMember
FROM
tblmembership
INNER JOIN tblpeople ON (tblmembership.PersonID = tblpeople.PersonID)
WHERE
tblpeople.MemSTATUS IN ('Back from VPM', 'Sent To VPM 2', 'Sent To VPM 1', 'Back from VPM', 'Renewal', 'Active Member')
GROUP BY YearsMember
HAVING YearsMember
ORDER BY YearsMember
Many times that makes things easier to process and come up with a solution.
Can’t edit my post… Was suppose to be “simplify”. Second, what database are you using?
MySql
How would you group them by the year ranges, thats what’s got me stumped
Use a CASE
statement, something like:
GROUP BY
SELECT CASE
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) <= 2 THEN '0-2'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) <= 5 THEN '3-5'
... etc ...
END
I am not too verse on MySQL so the syntax might be a bit wrong, but I’m sure you can figure it out from there.
Here is the working query for anybody else that needs an example:
SELECT Count(tblpeople.PersonID) AS Total,
CASE
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) BETWEEN 0 AND 2
THEN '0-2'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) BETWEEN 3 AND 5
THEN '3-5'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) BETWEEN 3 AND 10
THEN '6-10'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) BETWEEN 11 AND 20
THEN '11-20'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) BETWEEN 21 AND 30
THEN '21-30'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(tblmembership.MemberSince) > 30
THEN '>30'
END AS YearsMember
FROM tblmembership
INNER JOIN tblpeople ON tblmembership.PersonID = tblpeople.PersonID
WHERE tblpeople.MemSTATUS IN ( 'Back from VPM', 'Sent To VPM 2', 'Sent To VPM 1',
'Back from VPM', 'Renewal', 'Active Member')
GROUP BY YearsMember
ORDER BY YearsMember
Richard, glad you got it working. I am wondering, though, if it wouldn’t be easier and less error prone to use <= 2
, <= 5
, etc… No need for BETWEEN
. Also, the last statement could be ELSE
which would also reduce potential error and remove duplicate business logic.
You can also shorten things a bit by using an AS
SELECT
Count(p.PersonID) AS Total,
CASE
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(m.MemberSince) <= 2 THEN '0-2'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(m.MemberSince) <= 5 THEN '3-5'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(m.MemberSince) <= 10 THEN '6-10'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(m.MemberSince) <= 20 THEN '11-20'
WHEN YEAR(CURRENT_TIMESTAMP) - YEAR(m.MemberSince) <= 30 THEN '21-30'
ELSE '>30'
END AS YearsMember
FROM
tblmembership AS m
INNER JOIN tblpeople AS p ON (m.PersonID = p.PersonID)
WHERE
p.MemSTATUS IN ( 'Back from VPM', 'Sent To VPM 2', 'Sent To VPM 1', 'Back from VPM', 'Renewal', 'Active Member')
GROUP BY YearsMember
ORDER BY YearsMember
Oh, one more note. Your YEAR math could result in misleading information, depending on how your membership works. For example, Someone joins Dec 31st, 2012 and today is Jan 1st, 2015, it’ll show them in the 3-5 range, when really they are barely 2 years. You may wish to use DATEDIFF
, you will have to then think in days though.
Thanks for posting this. It will be valuable for others in the future. Too many threads pose a question, but do not include the solution after it’s been found. (I know I’ve been remiss in not doing this myself - guess being so relieved to have a knotty problem resolved that I forget to post the working solution…)