2017-10-09 21 views
2

Si mon sous-requête foo libère les lignes: -Postgres: compter les entrées de tableau uniques de sous-requête

ID, USERS 
1 {23129} 
2 {23142} 
3 {23300,23300} 
4 {23129,23300} 

Comment puis-je obtenir un nombre d'utilisateurs uniques dans une requête en utilisant une fonction de fenêtre, tels que: -

SELECT ... FROM (<subquery>) FOO 

J'ai essayé: -

array_length(array_agg(array_length(array(SELECT Distinct unnest(users))),1)) over(), 1) 

Mais obtenir l'erreur que les dimensions du tableau ne sont pas les mêmes

NOTE BIEN: Je ne peux pas modifier la sous-requête pour résoudre ce problème.

je peux obtenir les identifiants dans un tableau comme suit: -

string_to_array(string_agg(array_to_string(user_ids, ','), ',') over(),',') 

Mais ils ne sont pas distincts.

+0

Merci pour les réponses, le problème est que la sous-requête ne peut pas être modifiée. – CitizenFish

+0

'SELECT nombre (BAR distincte) FROM() FOO, unnest (FOO.USERS) AS BAR' – Abelisto

Répondre

1

Vous pouvez toujours utiliser un alghoritm connu dans une fonction SQL simple:

create or replace function array_unique_elements(arr anyarray) 
    returns integer 
    language sql immutable 
as $$ 
    select count(distinct a)::int 
    from unnest(arr) a 
$$; 

Utilisation:

select *, array_unique_elements(users) 
from (
    values 
    (1, '{23129}'::int[]), 
    (2, '{23142}'), 
    (3, '{23300,23300}'), 
    (4, '{23129,23300}') 
) foo (id, users) 

id |  users  | array_unique_elements 
----+---------------+----------------------- 
    1 | {23129}  |      1 
    2 | {23142}  |      1 
    3 | {23300,23300} |      1 
    4 | {23129,23300} |      2 
(4 rows) 
4

Vous êtes des choses trop compliquer - vous pouvez unnest le tableau, puis interroger un compte distinct de celui-ci:

SELECT COUNT(DISTINCT u) 
FROM (SELECT UNNEST(users) AS u 
     FROM mytable) t 
+0

Merci, mais la sous-requête ne peut pas être modifiée – CitizenFish

0

Je aussi bien juste compter distinct comme le suggère Mureinik.

Et en ce qui concerne l'erreur que vous obtenez - voici exemple de syntaxe étroite avec array_length:

t=# with a(v) as (values('{1,2}'::int[]),('{2,3}')) 
select array_length(array_agg(distinct unnest),1) from (
    select unnest(v) from a 
) a; 
array_length 
-------------- 
      3 
(1 row) 

Bien sûr, il NE avec l'agrégation de fenêtre - uniquement avec GROUP BY