2

If my subquery foo liberates the rows:-

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

How can I get a count of unique users in a query using a window function such as:-

SELECT ... FROM ( <subquery> ) FOO

I tried this:-

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

But get the error that the array dimensions are not the same

NOTE WELL: I cannot change the subquery to solve this problem.

I can get the IDs in an array as follows:-

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

But they are not distinct.

2
  • Thanks for the answers, problem is the subquery cannot be changed. Commented Oct 9, 2017 at 15:31
  • SELECT count(distinct BAR) FROM ( <subquery> ) FOO, unnest(FOO.USERS) AS BAR Commented Oct 9, 2017 at 19:37

3 Answers 3

6

You're overcomplicating things - you can unnest the array, and then query a distinct count from it:

SELECT COUNT(DISTINCT u)
FROM   (SELECT UNNEST(users) AS u
        FROM   mytable) t
Sign up to request clarification or add additional context in comments.

1 Comment

Thank but the subquery cannot be changed
1

You can always use a known alghoritm in a simple SQL function:

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

Use:

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)

Comments

-1

I would as well just count distinct as Mureinik suggests.

And regarding error that you get - here's tight syntax example with 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)

Of course it WILL NOT with window aggregation - only with GROUP BY

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.