2

我有一个查询,例如:

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)

我怎样才能让它为一行和一个表中的每个 where 条件返回一个结果:

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)
4

6 回答 6

2

如前所述,您可以使用一个案例并在一个查询中执行所有这些操作,但是您不需要使用子查询,尽管我不是它的忠实粉丝,MySQL 允许您在 group by 中使用列别名,所以以下将起作用:

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;

请注意,我仍然添加了 where 子句以避免扫描冗余数据。

SQL Fiddle 示例

但是,如果您缺少数据,则会下降,例如将返回一个空表,而不是这样:

AGERANGE    USER_LIST
15-19       0
20-24       0
25-29       0
30+         0

如您所料。为了解决这个问题,我将创建一个伪表以供选择,然后加入您的数据:

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;

SQL Fiddle 示例

于 2013-10-30T18:03:23.000 回答
1

试试这个方法

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 
于 2013-10-30T10:31:32.377 回答
0

以下 SQL 子句可以提供帮助:

Group by, Case, and Subqueries...查找它们并与之一起玩,自己弄清楚应该很有趣...

您可以考虑在查询中使用另一列(例如,15 到 18 之间的大小写,然后 1,大小写...然后 2,...)作为 Range,标识一个范围并按此分组...

这是一个示例,说明如何将您的范围标识为子查询中的列,并在按子查询中的范围分组的基础上进行查询:

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

这导致以下结果:

范围 | 数数

r1 | 10

r2 | 7

其中 r1 可以是与 case 子句中定义的“enrolled = 1 AND age >=20 AND age < 25”等相对应的范围。

于 2013-10-30T10:15:18.927 回答
0

你可以使用工会:

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)
于 2013-10-30T10:15:49.473 回答
0

使用 4 个简单查询而不是 1 个复杂查询,性能应该没有问题

于 2013-10-30T10:26:43.603 回答
0

这很简单

select count(1),ceil(age/5)*5 from tbl_users where enrolled=1 group by ceil(age/5)

于 2013-10-30T11:48:17.693 回答