Select column values linked to exact set of values in another column
Assuming a PRIMARY KEY on (chat_id, user_id) - or a UNIQUE constraint plus NOT NULL on both columns.

To allow any number of IDs, use a 1-dimensional array parameter:

SELECT chat_id
FROM   chats_users c
WHERE  user_id = ANY ('{1,2,3}'::int[])
GROUP  BY 1
HAVING count(*) = array_length('{1,2,3}'::int[], 1)
AND    NOT EXISTS (
   SELECT 1
   FROM   chats_users
   WHERE  chat_id = c.chat_id
   AND    user_id &lt;&gt; ALL ('{1,2,3}'::int[])
   );


Typically, in function or prepared statements, you provide the array parameter only once. Example for prepared statement:

PREPARE foo(int[]) AS
SELECT chat_id
FROM   chats_users c
WHERE  user_id = ANY ($1)
GROUP  BY 1
HAVING count(*) = array_length($1, 1)  -- all required user_id
AND    NOT EXISTS (
   SELECT 1
   FROM   chats_users
   WHERE  chat_id = c.chat_id
   AND    user_id &lt;&gt; ALL ($1)  -- no additional user_id
   );


Tests:    

EXECUTE foo('{1,2,3}');  -- 1
EXECUTE foo('{1,3}');    -- 2
EXECUTE foo('{2,3}');    -- 3
EXECUTE foo('{1,2}');    -- empty


db&lt;>fiddle here
Old sqlfiddle.

That's basically the first solution by Martin in this related answer on SO (with some modifications to fit your case):


How to filter SQL results in a has-many-through relation?


There are faster solutions for a small, given number of IDs.