id | name | 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
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