I have a PostgreSQL table:
create table test(type_id, m_id)as values
(1, 123)
,(2, 456)
,(3, 123)
,(4, 123)
,(2, 456)
,(1, 789)
;
Basically, one m_id
could have multiple rows in this table associated with different type_id
s.
How can I find m_id
s that have type_id
s only of value 2
? In this example, it’s the m_id
of 456
only.
I tried to group by m_id
, but didn’t really work out well. Any ideas please?
Thanks!
2
Answers
You’re on the right track with the
group by
idea. Just addhaving
clause to that:demo at db<>fiddle
The
every()
/bool_and()
function checks a condition for all rows in the group so it makes sure alltype_id
‘s appearing with a givenm_id
are a2
. Or, that there doesn’t exist a row in that group for which that expression evaluates tofalse
.You can also use an
exists
:Or an anti-join:
Or an
except
:Here’s a test where there’s 13 such
m_id
‘s buried among 200k other in a heap of 900k randomised rows. It shows that bothexists
and the explicitanti-join
examples result in a nested loop anti-join plan that outperforms the rest, at just3ms
. That’s thanks to these covering indexes:Having
needed253ms
andexcept
took530ms
, even though they had also been given adequate indexes.