按多个标准分组

时间:2013-04-23 00:35:58

标签: sql postgresql aggregate-functions

给出像

这样的表格
| userid | active | anonymous |
|   1    |   t    |    f      |
|   2    |   f    |    f      |
|   3    |   f    |    t      |

我需要得到:

  • 用户数
  • 'active'= true
  • 的用户数量
  • '有效'= false
  • 的用户数量
  • 'anonymous'= true
  • 的用户数量
  • 'anonymous'= false
  • 的用户数量

单一查询。

就目前而言,我只使用 union

推出解决方案
SELECT count(*) FROM mytable
UNION ALL
SELECT count(*) FROM mytable where active
UNION ALL
SELECT count(*) FROM mytable where anonymous

所以我可以使用第一个号码,并通过简单的扣除找到非活跃和非匿名用户。

有没有办法摆脱联合并计算符合这些简单条件的记录数量以及 PostgreSQL 9 中的魔术和高效查询?

2 个答案:

答案 0 :(得分:3)

您可以使用带CASE的聚合函数将结果放在单独的列中:

select 
  count(*) TotalUsers,
  sum(case when active = 't' then 1 else 0 end) TotalActiveTrue,
  sum(case when active = 'f' then 1 else 0 end) TotalActiveFalse,
  sum(case when anonymous = 't' then 1 else 0 end) TotalAnonTrue,
  sum(case when anonymous = 'f' then 1 else 0 end) TotalAnonFalse
from mytable;

请参阅SQL Fiddle with Demo

答案 1 :(得分:2)

假设您的列为boolean NOT NULL,这应该会更快一些:

SELECT total_ct
      ,active_ct
      ,(total_ct - active_ct) AS not_active_ct
      ,anon_ct
      ,(total_ct - anon_ct) AS not_anon_ct
FROM  (
   SELECT count(*) AS total_ct
         ,count(active OR NULL) AS active_ct
         ,count(anonymous OR NULL) AS anon_ct
   FROM  tbl
   ) sub;

详细解释这个密切相关答案中使用的技巧:
Compute percents from SUM() in the same SELECT sql query

索引几乎没有任何用处,因为无论如何都必须读取整个表格。如果您的行大于示例中的行,则覆盖索引可能会有所帮助。取决于您的实际表格的具体情况。

- > SQLfiddle与每个值的@bluefeet's version with CASE statements进行比较。

SQL服务器用户不习惯boolean类型的Postgres,并且往往会走很长的路。