2012-02-04 59 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