2012-02-04 27 views
4

我想要的是对任何单个事件计数与true(出席),false(不出席)和NULL相对应的数组元素。PostgreSQL计数数组值

编辑:

我刚刚意识到阵列不表现为我在PSQL想到,这么一个简单的

userconfirm bool[] 

就足够。不过,我仍然有计算true/false/null值的相同问题。我将尝试编辑下面的问题以匹配这个新的约束。我对任何错误表示歉意。


我有一列如

userconfirm bool[] 

userconfirm[314] = true将意味着用户#314将出席。 (false =没有参加,NULL =没有读取/ etc)。

我不确定这是用于此功能的最佳解决方案(用户宣布他们出席某个事件),但我在此列上的聚合函数遇到问题。

select count(*) from foo where id = 6 AND true = ANY (userconfirm); 

这只返回1,并试图谷歌“计数阵列”没有任何有用的东西。

我该如何计算单个事件的不同值?

回答

2

您可以使用unnest在SELECT这样的:

select whatever, 
     (select sum(case b when 't' then 1 else 0 end) from unnest(userconfirm) as dt(b)) 
from your_table 
-- ... 

例如,给定这样的:

=> select * from bools; 
id |  bits  
----+-------------- 
    1 | {t,t,f} 
    2 | {t,f} 
    3 | {f,f} 
    4 | {t,t,t} 
    5 | {f,t,t,NULL} 

你会得到这样的:

=> select id, (select sum(case b when 't' then 1 else 0 end) from unnest(bits) as dt(b)) as trues from bools; 
id | trues 
----+------- 
    1 |  2 
    2 |  1 
    3 |  0 
    4 |  3 
    5 |  2 

如果这太丑了,你可以写一个功能:

create function count_trues_in(boolean[]) returns bigint as $$ 
    select sum(case b when 't' then 1 else 0 end) 
    from unnest($1) as dt(b) 
$$ language sql; 

,并用它来靓起来您的查询:

=> select id, count_trues_in(bits) as trues from bools; 
id | trues 
----+------- 
    1 |  2 
    2 |  1 
    3 |  0 
    4 |  3 
    5 |  2 
+0

这似乎工作。我可以用'f'来反转它以得到相反的结果。我不认为你会知道如何获得真实的索引列表?例如。它返回'1,4,314'。 – TLP 2012-02-04 23:06:07

+0

@TLP:我认为你可以用'unnest'和'generate_series'组合来完成它; 'unnest'打开数组和'generate_series'来提供索引号。然后'array_agg'将它们放回到一起。 – 2012-02-04 23:17:55

+0

@TLP:或者'rank()over'来提供索引。 – 2012-02-04 23:25:47

1

你可以总和array_length功能结果:

SELECT SUM(array_length(userconfirm, 2)) WHERE id = 6; 
+1

我很抱歉,我才意识到我的问题已经改变。阵列不像我想的那样工作(来自perl)。我使用'bool []'来代替。总结数组长度似乎并不是正确的解决方案,因为我得到293作为具有两个非空值的数组的总和。 – TLP 2012-02-04 19:48:56

0

这一个可以做的伎俩(unnest)。

postgres=# with y(res) as (
postgres(#    with x(a) as (
postgres(#      values (ARRAY[true,true,false]) 
postgres(#      union all 
postgres(#      values (ARRAY[true,null,false]) 
postgres(#    ) 
postgres(#    select unnest(a) as res 
postgres(#    from x 
postgres(#  ) 
postgres-# select count(*) 
postgres-# from y 
postgres-# where res; 
count 
------- 
    3 
(1 row) 


postgres=# 
+0

这似乎非常复杂。我将如何将这个应用到我的桌子上?我没有比较两个数组,我想比较一个数组与一个值。 – TLP 2012-02-04 20:19:30

+0

unnest函数将数组分解为表结构(y子查询)。在转换为单个列表的数组上,您可以在评估条件的SQL查询上使用count(*)。寻找res = true,与检查res相同。 – 2012-02-04 20:26:22