以1行和不同列显示结果

时间:2013-06-19 20:19:49

标签: mysql sql select

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

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

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

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

如果想知道在一个查询中有多少打开以及关闭了多少关闭结果,则返回两列,即

Open | Closed|  
  60    180   

最好的方法是什么? UNION连接结果,因此它不是我想要的

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:4)

试试这个

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