Thursday, August 4, 2011

MySQL Query - count age by range

Now I have a condition to query on my MySQL database like following: I have a table, let's called it user_table and in the table I have columns including id, name, email, phone, birthday as the following:

id name email tel birthday
1 name1 email1 2144 1976-01-01
2 name2 email2 5436457 NULL
3 name3 email3 0976564765 1987-01-01
4 name4 email4 1243412 NULL
5 name5 email5 87432145 NULL
6 name6 email6 5777 NULL
7 name7 email7 9875847567 NULL
8 name8 email8 9854875463 1976-01-01
9 name9 email9 27557666 1966-01-01
10 name10 email10 8765765765 1976-01-01
11 name11 email11 0912564421 1984-01-01
12 name12 email12 0955711114 1986-01-01
13 name13 email13 123 1991-01-01
14 name14 email14 0955711115 NULL

What I want to do is to make a query that will group and count the user by age range. The result that I want, is like following:

Under 20 20 - 29 30 - 39 40 - 49 50 - 59 60 - 69 70 - 79 Over 80 Not Filled In
0 4 3 1 0 0 0 0 6

Before I started to look for an answer in the internet, I was thinking to achieve this result, may be I could use php and did the looping of  MySQL query which contains SELECT, COUNT and GROUP BY on different range of age, but this way is not a direct or a pretty solution. So, I tried to search on the internet of how to do it with pure MySQL query. And after searching on the internet I found out the solution as the following:

SELECT
        SUM(IF(age < 20,1,0)) as 'Under 20',
        SUM(IF(age BETWEEN 20 and 29,1,0)) as '20 - 29',
        SUM(IF(age BETWEEN 30 and 39,1,0)) as '30 - 39',
        SUM(IF(age BETWEEN 40 and 49,1,0)) as '40 - 49',
        SUM(IF(age BETWEEN 50 and 59,1,0)) as '50 - 59',
        SUM(IF(age BETWEEN 60 and 69,1,0)) as '60 - 69',
        SUM(IF(age BETWEEN 70 and 79,1,0)) as '70 - 79',
        SUM(IF(age >=80, 1, 0)) as 'Over 80',
        SUM(IF(age IS NULL, 1, 0)) as 'Not Filled In (NULL)'
FROM (SELECT YEAR(CURDATE())-YEAR(birthday)) AS age FROM user_table) as derived

From this solution we see that actually it's not necessary to use COUNT AND GROUP BY to count on how many records that fit to certain range or condition. And in fact this solution turns the vertical data into horizontal data, which can't be achieved through COUNT and GROUP BY (as I know, correct me if I'm wrong!).

As a novice, this solution clarified my concept and ideas in MySQL, such as:

1. In FROM we can put another sub-query and what the sub-query return is actually a table that gonna be used to do another query by the main query. Let me give you an instance of what I mean! Usually we do the query like this: SELECT * FROM user_table [WHERE condition], but in another situation we need to select something from a query result and give it as an input or a source table to another query, particularly the main query as you can see in the above solution: SELECT  SUM(IF(age < 20,1,0)) as 'Under 20', ...  FROM (SELECT YEAR(CURDATE())-YEAR(birthday)) AS age FROM user_table) as derived


2. Another thing is that we can use SUM without having to use GROUP BY, I used to think that whenever I need to use SUM, I should also use GROUP BY.

3. In MySQL we can make a conditional test that return a value with  this syntax: IF(condition,value to return when condition is true, value to return when condition is false), e.g. If age is smaller than 20, then return 1, else return 0. The corresponding MySQL is like following: IF(age > 20 , 1 , 0)


4. To get current year in MySQL use: YEAR(CURDATE());



No comments:

Post a Comment