2013-04-23 56 views
1

鉴于表像集团由多个条件

| userid | active | anonymous | 
| 1 | t | f  | 
| 2 | f | f  | 
| 3 | f | t  | 

我需要得到:

  • 用户数
  • 号与“主动” =真
  • 的用户数量的用户'active'= false
  • '匿名'= true的用户数
  • “匿名”= false的用户数

单个查询。

至于现在,我只用工会解出来了:

SELECT count(*) FROM mytable 
UNION ALL 
SELECT count(*) FROM mytable where active 
UNION ALL 
SELECT count(*) FROM mytable where anonymous 

所以我可以把第一号和找到简单的扣除非活动和非匿名用户。

有什么办法摆脱工会和计算的一些魔术和高效查询在PostgreSQL的9符合这些条件简单的记录是多少?

+0

您忘记提及您的表的NOT NULL约束,主键,数据类型和其他相关信息。还有PostgreSQL 9.? - [第一*和*版本号的第二部分与主要版本相关。](http://www.postgresql.org/support/versioning/) – 2013-04-23 01:49:15

回答

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服务器人员不习惯Postgres的正确boolean类型,并倾向于走很长的路。

+0

我知道你会得到一个更好的postgreSQL答案。我想我需要多学点这个数据库。 – Taryn 2013-04-23 13:47:53

+0

@bluefeet:我尽我所能。 ;)仅仅学习主要的RDBMS版本也太多了。 – 2013-04-23 13:54:08

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

+0

我查看了执行计划并意识到,这个查询没有使用我在表上的任何索引,例如'在mytable((anonymous = true))'上创建索引table_anon''。所以它有'seq扫描'并且不使用任何过滤器。 – jdevelop 2013-04-23 01:12:47