1

假设一个简单的情况,例如一个表bug,其中有一列status可以是openfixed
如果我想知道有多少错误是打开的,我只需这样做:

select count(*) as open_bugs from bugs where status = 'open';

如果我想知道有多少错误是开放的,我只需这样做:

select count(*) as closed_bugs from bugs where status = 'closed';

如果想知道在 2 列中返回结果的查询中有多少打开和关闭多少,即

Open | Closed|  
  60    180   

最好的方法是什么?UNION连接结果所以这不是我想要的

4

3 回答 3

8

这可以通过在聚合函数中使用 CASE 表达式来完成。这会将行转换为列:

select
    sum(case when status = 'open' then 1 else 0 end) open_bugs,
    sum(case when status = 'closed' then 1 else 0 end) closed_bugs
from bugs

这也可以使用您的原始查询编写:

select 
   max(case when status = 'open' then total end) open_bugs,
   max(case when status = 'closed' then total end) closed_bugs
from
(
  select status, count(*) as total from bugs where status = 'open' group by status
  union all
  select status, count(*) as total from bugs where status = 'closed' group by status
) d
于 2013-06-19T20:22:48.837 回答
7

除了在CASE整个表上聚合的变体之外,还有另一种方法。要使用您拥有的查询并将它们放在另一个中SELECT

SELECT 
  ( SELECT COUNT(*) FROM bugs WHERE status = 'open')   AS open_bugs, 
  ( SELECT COUNT(*) FROM bugs WHERE status = 'closed') AS closed_bugs 
FROM dual      -- this line is optional 
 ; 

它的优点是您可以将来自不同表或连接的计数包装在单个查询中。

效率也可能存在差异(更差或更好)。使用您的表和索引进行测试。

您还可以使用GROUP BY在单独的行中获取所有计数(就像UNION您提到的那样),然后使用另一个聚合将结果旋转到一行中:

SELECT 
  MIN(CASE WHEN status = 'open'   THEN cnt END) AS open_bugs, 
  MIN(CASE WHEN status = 'closed' THEN cnt END) AS closed_bugs
FROM 
  ( SELECT status, COUNT(*) AS cnt
    FROM bugs 
    WHERE status IN ('open', 'closed')
    GROUP BY status 
  ) AS g
于 2013-06-19T20:34:06.317 回答
4

尝试这个

select count(case when status = 'open' then 1 end) open_bugs,
count(case when status = 'closed' then 1 end) closed_bugs
from bugs
于 2013-06-19T20:21:57.157 回答