0

I'd like to get all of the groups of records that have a specific value (or set of values) within a string array in PostgresSQL. For example, take the following table

+---------+------------+--------+
| user_id |    date    | group  |
+---------+------------+--------+
|       1 | 2019-02-06 | groupA |
|       1 | 2019-02-06 | groupB |
|       1 | 2019-02-06 | groupC |
|       2 | 2019-02-06 | groupB |
|       2 | 2019-02-06 | groupC |
|       3 | 2019-02-06 | groupA |
|       3 | 2019-02-06 | groupC |
+---------+------------+--------+

I can group them with the following query:

SELECT
   user_id,
   date,
   string_agg(group, ',') as groups
FROM t
GROUP BY
   user_id,
   date

which gives the following;

+---------+------------+-------------------------+
| user_id |    date    |         groups          |
+---------+------------+-------------------------+
|       1 | 2019-02-06 |  {groupA,groupB,groupC} |
|       2 | 2019-02-06 |  {groupB,groupC}        |
|       3 | 2019-02-06 |  {groupA,groupC}        |
+---------+------------+-------------------------+

But I only want groups that contain groupA. That is, here is the desired output:

+---------+------------+-------------------------+
| user_id |    date    |         groups          |
+---------+------------+-------------------------+
|       1 | 2019-02-06 |  {groupA,groupB,groupC} |
|       3 | 2019-02-06 |  {groupA,groupC}        |
+---------+------------+-------------------------+

How do I filter out rows that don't contain groupA?

Here's one query I've tried unsuccessfully:

SELECT
   user_id,
   date,
   string_agg(group, ',') as groups
FROM t
GROUP BY
   user_id,
   date
HAVING 'groupA' IN string_agg(group, ',')

1 Answer 1

1

INcan't be used with lists of elements, string_agg() returns a single character value.

But you can aggregate the values into an array that can be used in the having clause:

SELECT user_id,
       "date",
       string_agg("group", ',') as groups
FROM t
GROUP BY user_id, "date"
HAVING 'groupA' = any (array_agg("group"));

Another option is to use the contains operator @>

SELECT user_id,
       "date",
       string_agg("group", ',') as groups
FROM t
GROUP BY user_id, date
HAVING array_agg("group") @> array['groupA']::varchar[]
2
  • Thanks! The first method works for me, but the second method returns the following error: "ERROR: operator does not exist: character varying[] @> text[] Hint: No operator matches the given name and argument type(s). You may need to add explicit type casts." I tried tacking on a ::varchar at the end to cast, but that didn't work. Commented Feb 6, 2019 at 21:25
  • I assumed "group" (which is a horrible name) was defined as text. But you can cast the array to a varchar[] (see my edit) or use array['groupA'::varchar] Commented Feb 6, 2019 at 21:30

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.