Reputation: 181
I have a query such as:
SELECT COUNT(id) AS user_list FROM tbl_users
WHERE (enrolled = 1 AND age >=15 AND age < 20)
OR (enrolled = 1 AND age >=20 AND age < 25)
OR (enrolled = 1 AND age >=25 AND age < 30)
OR (enrolled = 1 AND age >=30)
How can I have it return a result for each where condition in one row and one table as such:
user_list
---------
18 --(enrolled = 1 AND age >=15 AND age < 20)
12 --(enrolled = 1 AND age >=20 AND age < 25)
22 --(enrolled = 1 AND age >=25 AND age < 30)
56 --(enrolled = 1 AND age >=30)
Upvotes: 2
Views: 927
Reputation: 69769
As has been mentioned you can use a case and perform this all in one query, however you don't need to use a subquery, although I am not a massive fan of it, MySQL allows you to use column aliases in the group by, so the following will work:
SELECT CASE WHEN (enrolled = 1 AND age >=15 AND age < 20) THEN '15-19'
WHEN (enrolled = 1 AND age >=20 AND age < 25) THEN '20-24'
WHEN (enrolled = 1 AND age >=25 AND age < 30) THEN '25-29'
WHEN (enrolled = 1 AND age >=30) THEN '30+'
ELSE 'Other'
END AS AgeRange
COUNT(id) AS user_list
FROM tbl_users
WHERE Enrolled = 1
AND Age >= 15
GROUP BY AgeRange;
Note, I have still added a where clause to avoid scanning redunant data.
This falls down however if you have missing data, e.g. an empty table will return, not this:
AGERANGE USER_LIST
15-19 0
20-24 0
25-29 0
30+ 0
As you might expect. To get around this I would create a pseudo table to select from, and left join your data:
SELECT t.Name AS Age_Range,
COUNT(u.ID) AS User_List
FROM ( SELECT '15-19' AS Name, 15 AS LowerBound, 20 AS UpperBound, 1 AS Enrolled
UNION ALL
SELECT '20-24' AS Name, 20 AS LowerBound, 25 AS UpperBound, 1 AS Enrolled
UNION ALL
SELECT '25-29' AS Name, 25 AS LowerBound, 30 AS UpperBound, 1 AS Enrolled
UNION ALL
SELECT '30+' AS Name, 30 AS LowerBound, 9999999 AS UpperBound, 1 AS Enrolled
) t
LEFT JOIN tbl_Users u
ON u.Enrolled = t.enrolled
AND u.Age >= t.LowerBound
AND u.Age < t.UpperBound
GROUP BY t.Name;
Upvotes: 2
Reputation: 1
this is simple
select count(1),ceil(age/5)*5 from tbl_users where enrolled=1 group by ceil(age/5)
Upvotes: 0
Reputation: 577
There are the following SQL clauses that could help:
Group by
, Case
, and Subqueries
...look them up and play with that, should be fun to figure it out yourself...
You could look into having another column in your query (e.g. case between 15 and 18 then 1, case ... then 2, ...) as Range, identifying a range and grouping by that...
This is an example of how to identify your ranges as columns in a subquery, and query on top of that grouped by the ranges in your subquery:
select count(*) as Count, r as Range
from
(select
(case
when enrolled = 1 AND age >=20 AND age < 25 then 'r1'
when enrolled = 1 AND age >=25 AND age < 30 then 'r2'
end) as r
from Text)
as groups
group by r
This results in the following:
Range | Count
r1 | 10
r2 | 7
where r1 can be your range corresponding to "enrolled = 1 AND age >=20 AND age < 25" or so on, defined in the case clause.
Upvotes: 0
Reputation: 13700
Try this method
create table t (list1 int,list2 int,list3 int,list4 int)
insert into t
SELECT
SUM(case when age >=15 AND age < 20 then 1 else 0 end) AS user_list1,
SUM(case when age >=20 AND age < 25 then 1 else 0 end) AS user_list2,
SUM(case when age >=25 AND age < 30 then 1 else 0 end) AS user_list3,
SUM(case when age >=15 AND age < 20 then 1 else 0 end) AS user_list4
FROM tbl_users
WHERE enrolled = 1 ;
select list1 from t union all
select list2 from t union all
select list3 from t union all
select list4 from t
Upvotes: 1
Reputation: 1320
There should not be problem for performance to use 4 simple queries instead of one complicated
Upvotes: 0
Reputation: 707
U could use unions:
SELECT COUNT(id) AS user_list
FROM tbl_users
WHERE (enrolled = 1 AND age >= 15 AND age < 20)
union
SELECT COUNT(id)
FROM tbl_users
where (enrolled = 1 AND age >= 20 AND age < 25)
union
SELECT COUNT(id)
FROM tbl_users
where (enrolled = 1 AND age >= 25 AND age < 30)
union
SELECT COUNT(id) FROM tbl_users where (enrolled = 1 AND age >= 30)
Upvotes: 0