Given the table below, I’m trying to find a way to get the group matching a pre-defined subset of tokens BUT the group should not contain any tokens outside of the subset.
group | token |
---|---|
3 | 37 |
1 | 34 |
1 | 32 |
3 | 32 |
3 | 34 |
Example: I want to select the group containing tokens (32, 34).
Problem: Doing a GROUP BY group
and an IN (32, 34)
condition will mean receiving both group 3 and group 1. However, group 3 should be omitted on the basis that it also has a token
with value 37
which is not in my subset.
Efforts:
-
Attempted
string_agg
on thetoken
column with different comparison operators which check the list ofgroup
columns that were selected based ontoken
matching one value in my subset(32, 34)
. This got messy very quickly and resulted in type conversions and elaborate string comparisons. -
Attempted a nested query which would first extract a list of
group
ids as long as one of thetoken
values were in my list, and then attempting to count the totaltoken
belonging to group and comparing it to the length of my subset. Due to the implementation of this table and how it’s used, it would be a sufficient solution since I’m guaranteed no duplication of groups containing the specified token set but it is definitely not ideal.
2
Answers
Use a having clause to determine if the count of in(32,34) is greater tan 1 but also that the count for any other token is zero. e.g:
fiddle
nb "not in()" can produce unexpected results if it encounters a null so I usually avoid it and so I have avoided that through the where clause. Here it is is not essential as tested at the fiddle above. Another approach without the where clause:
If your set is in table
s
like belowAnd your table is
t
.You can left join table
t
with tables
.You can see null in token column of
s
table. That null means37
value not exists ins
table.Now you need to exclude by changing null to -1 (or whatever value smaller than any values) and check it in having statement.
http://sqlfiddle.com/#!17/cc1cb9/8