简体   繁体   English

在MySQL中,如何使用case语句重写查询?

[英]In MySQL how to rewrite a query using a case statement?

I have a MySQL table: 我有一个MySQL表:

create table tbl (
  amount int
);

insert into tbl (amount) values (1);
insert into tbl (amount) values (2);
insert into tbl (amount) values (3);
insert into tbl (amount) values (4);

My goal is a report of how many values are in the following buckets, by using a case statment. 我的目标是通过使用案例陈述报告以下存储桶中有多少值。

Bucket A: values 0-1 值区A:值0-1
Bucket B: values 2-5 值区B:值2-5
Bucket C: values 6-9 值区C:值6-9

First lets try a simple query: 首先让我们尝试一个简单的查询:

select "Bucket A" as Bucket, count(amount) "Count"
from tbl
where amount in (0,1)
union
select "Bucket B" as Bucket, count(amount) "Count"
from tbl
where amount in (2,3,4,5)
union
select "Bucket C" as Bucket, count(amount) "Count"
from tbl
where amount in (6,7,8,9);

Result: 结果:

+----------+-------+
| Bucket   | Count |
+----------+-------+
| Bucket A |     1 |
| Bucket B |     3 |
| Bucket C |     0 |
+----------+-------+

Results are perfect, but I want a case statement. 结果是完美的,但我需要一个案例说明。
So I try this: 所以我尝试这样:

select 
sum(case when amount in (0,1) then 1 else 0 end) as "Bucket A",
sum(case when amount in (2,3,4,5) then 1 else 0 end) as "Bucket B",
sum(case when amount in (6,7,8,9) then 1 else 0 end) as "Bucket C"
from tbl;

Result: 结果:

+----------+----------+----------+
| Bucket A | Bucket B | Bucket C |
+----------+----------+----------+
|        1 |        3 |        0 |
+----------+----------+----------+

Values are correct, and great that I have a case statement, but problem is the values got pivoted. 值是正确的,并且我有一个case语句,这很好,但是问题是值变得很重要。

How can I 我怎样才能
1. use a case statement 1.使用案例陈述
2. have no pivot? 2.没有枢纽?

You can do this using aggregation: 您可以使用聚合来执行此操作:

select (case when amount in (0, 1) then 'Bucket A'
             when amount in (2, 3,4, 5) then 'Bucket B'
             when amount in (6, 7, 8, 9) then 'Bucket C'
        end) as bucket, count(*) as `count`
from tbl
where amount in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
group by (case when amount in (0, 1) then 'Bucket A'
               when amount in (2,3,4,5) then 'Bucket B'
               when amount in (6,7,8,9) then 'Bucket C'
           end);

EDIT: 编辑:

Digital Chris makes a very good point. 数字克里斯提出了一个很好的观点。 This can be solved by using left outer join : 这可以通过使用left outer join来解决:

select (case when tbl.amount in (0, 1) then 'Bucket A'
             when tbl.amount in (2, 3,4, 5) then 'Bucket B'
             when tbl.amount in (6, 7, 8, 9) then 'Bucket C'
        end) as bucket, count(tbl.amount) as `count`
from (select 0 as amount union all
      select 2 as amount union all
      select 6 as amount
     ) throwaway left outer join
     tbl
     on throwaway.amount = tbl.amount
where tbl.amount in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
group by (case when tbl.amount in (0, 1) then 'Bucket A'
               when tbl.amount in (2,3,4,5) then 'Bucket B'
               when tbl.amount in (6,7,8,9) then 'Bucket C'
           end);

Or, perhaps more clearly, by using the original query as a subquery: 或者,也许更清楚地讲,通过使用原始查询作为子查询:

select buckets.bucket, coalesce(`count`, 0) as `count`
from (select 'Bucket A' as bucket union all
      select 'Bucket B' union all
      select 'Bucket C'
     ) buckets left outer join
     (select (case when amount in (0, 1) then 'Bucket A'
                   when amount in (2, 3,4, 5) then 'Bucket B'
                   when amount in (6, 7, 8, 9) then 'Bucket C'
              end) as bucket, count(*) as `count`
      from tbl
      where amount in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
      group by (case when amount in (0, 1) then 'Bucket A'
                     when amount in (2,3,4,5) then 'Bucket B'
                     when amount in (6,7,8,9) then 'Bucket C'
                 end)
     ) g
     on buckets.bucket = g.bucket;
select 
"Bucket A" as "Bucket", sum(case when amount in (0,1) then 1 else 0 end) as "Count" from tbl
UNION
select "Bucket B", sum(case when amount in (2,3,4,5) then 1 else 0 end) from tbl
UNION
select "Bucket C", sum(case when amount in (6,7,8,9) then 1 else 0 end) from tbl;

Like this? 像这样? sqlfiddle sqlfiddle

SELECT "Bucket A" AS Bucket ,
(SELECT SUM(CASE WHEN amount IN (0,1) THEN 1 ELSE 0 END) FROM tbl) AS "COUNT" 
UNION
SELECT "Bucket B" AS Bucket ,
(SELECT SUM(CASE WHEN amount IN (2,3,4,5) THEN 1 ELSE 0 END) FROM tbl) AS "COUNT" 
UNION
SELECT "Bucket C" AS Bucket ,
(SELECT SUM(CASE WHEN amount IN (6,7,8,9) THEN 1 ELSE 0 END) FROM tbl) AS "COUNT" 

sqlfiddle demo sqlfiddle演示

Use a manufactured list of bucket names, then left join to the table: 使用生成的存储桶名称列表,然后左联接表:

select concat('Bucket ', b) bucket, count(amount) count
from (select 'A' as b union select 'B' union select 'C') a
left join tbl on b = 
  case when amount in (0, 1) then 'A'
       when amount in (2,3,4,5) then 'B'
       when amount in (6,7,8,9) then 'C' end
group by 1

This will produce a row with a zero count when no rows for the bucket are found. 如果找不到存储桶的行,这将产生一个计数为零的行。

See SQLFiddle 参见SQLFiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM