假设一个简单的案例,例如表格bug
,其中status
列可以是open
,fixed
等。
如果我想知道有多少错误是打开的,我只是这样做:
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
连接结果,因此它不是我想要的
答案 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