I have 2 tables with the following schemas:

t1(id, type) where id and type are the primary key

t2(type, rate) where type is the primary key

I want to find all id's which appear with all types from t2.

For example given the tables:


 id | type
  1 | a 
  1 | b
  1 | c
  2 | a
  2 | b

and t2:

 type | rate
    a | 100
    b | 100
    c | 200

We can see that there're 3 unique types in t2 and only id 2 from t1 appears with all of them.

I figured out a way to get the id's by counting the number of unique types and then grouping t1 by id's and selecting only those whose count equals of the total number of types from t2.

But I was wondering if there're other logical constructs like in/not in, exists or Cartesian product which can also be used here with more elegance?


3 Answers 3


I don't know postgresql but shouldn't the following work?

select id
from t1
join t2 on t1.type = t2.type
group by id
having count(1) = (select count(1) from t2)

You are selecting the ID values.

The join means the type value on t1 must exist in t2. (I note you did not explicitly state there is a foreign key relationship there - hence this join, to avoid the case where, say, you have three distinct type values in t1 for a given ID value, but they are not the same three distinct type values in t2).

We use group by for two reasons: first, it means each ID will receive only 1 row in the output, but more importantly, this allows us to use the aggregate count function.

The count function essentially counts the number of rows for the given ID value (given the group by clause) and we are saying that number of rows must match the number of rows in t2. We can leave it as simply as that because type - the column we are interested in - in t2, is a key column and so will be unique across each row.

Wondering if I've missed something, in my postgresql ignorance?

Edit: Seems to work fine to me. I've used the setup SQL from another answer here to create a SQL Fiddle showing my solution against your question data.

View the SQL Fiddle


I dont think there is any logical constructs like in/not in.

But you can check array equality like below,

select id from 
(select array_agg(type)as type, id from t1  group by id) table_1 
(select array_agg(type)as type from t2)table_2 
on table_1.type=table_2.type;

May be this is useful to you :)

  • 1
    Arrays are not sets, so testing for equality will have problems with both order and duplication. You would want to construct your arrays using DISTINCT and ORDER BY if you go this route.
    – jjanes
    Sep 24, 2018 at 14:33
drop table if exists t1;
drop table if exists t2;
create table t1 (
    id int
    ,type varchar(1)

-- PKs are not necessary for the solution, but was part of OP's question,
-- so I included it anyway
alter table t1 add primary key (id, type);

create table t2 (
    type varchar(1) primary key
    ,rate int

insert into t1 (id, type) values
--(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'); -- test 1
(3, 'a'), (3, 'b'), (3, 'c'), (4, 'a'), (4, 'b'), (4, 'c'); -- test 2
--(5, 'a'), (5, 'b'), (5, 'c'); -- test 3

insert into t2 (type, rate) values
('a', 100), ('b', 100), ('c', 200);

with cteGroupCounts as (
    select id, count(*) as id_count from t1
    group by id
, cteMaxCount as (
    select max(id_count) as max_id_count
    from cteGroupCounts
, cteList as (
    select id from cteGroupCounts as G
    inner join cteMaxCount as M on G.id_count = M.max_id_count
select id from cteList

Somehow I think you may be able to solve this with windowing functions, but this seems to work.

  • this is similar to the method I used as I described in the OP. I was wondering regarding exists and/or not/in all
    – Yos
    Sep 26, 2018 at 5:45
  • @Yos - see my answer below for just a few lines of simple SQL using join, group by, having and a count of the number of required rows. It does not use exists or in but I'm wondering why you specifically want that in the solution? Oct 31, 2018 at 23:50

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.