2013-06-19 89 views
1

假设一个简单的例子,例如表bug有一列status,可以是openfixed
如果我想知道有多少错误是开放的,我只是做:以1行和不同列显示结果

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

试试这个

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

的情况下基本上越过每一行并创建一个1/0s的“不可见”行,并在外部的'select'中加上它们,对吧? – Cratylus

+0

是的,这将返回1匹配的条件和null为他人。当你计算它会做计数有价值的行 –

8

这可以通过使用与您的聚合函数CASE表达式做什么。这将行转换为列:

​​

这也使用原来的查询中写:

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 
+0

案件基本上遍及每一行,并创建一个“不可见”行与1/0s和外部'选择'它总结它们,对吧? – Cratylus

+1

由于这是汇总数据,因此只包含与案例中的“状态”匹配的行。它只是将where过滤器移到聚合函数。 – Taryn

+1

不是我会用第二个版本来推广非标准的SQL ......但是,第一个版本上的+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