John Jiang
John Jiang

Reputation: 11509

SQL Join Question

I have the following tables:

Table: user_groups (many-to-many)

Table: profile_groups (many-to-many)

So basically, I want to write a sql script to find out what profile is assigned to each user.

So in the end there should be only 2 columns: user_id and profile_id.

How would I go about doing this?

Edit: It's actually a lot more complicated than a simple join.

E.g.

User_groups may have the following rows

and profile_groups may have the following:

So the result should be

Each user should only have ONE profile

Upvotes: 0

Views: 239

Answers (4)

just somebody
just somebody

Reputation: 19257

jjia6395, judging from the comments below zzzeek's answer, you want to use the ALL operator. BTW, your question is terribly unclear, the edit didn't help.

Upvotes: 0

zzzeek
zzzeek

Reputation: 75317

I just saw a question like this the other day. I think the hard part here is you're looking for user_id/profile_id combinations where the user_id has every group_id that the profile_id has, no more and no less. So take the usual join and add some correlation to count the number of group_ids each profile/user has and make sure they match (this has been edited a few times):

 select user_id, profile_id 
    from user_groups join profile_groups on 
    user_groups.group_id=profile_groups.group_id 
    group by user_id, profile_id
    having count(user_groups.group_id) = 
    (select count(*) from profile_groups as pg where 
    pg.profile_id=profile_groups.profile_id)
    and count(profile_groups.group_id) = (select count(*) from user_groups as ug where 
    ug.user_id=user_groups.user_id)
    ;

Here's a run which includes two profiles with three groups each, with one common group between them and a new user in the fourth profile:

sqlite>  create table user_groups (user_id integer, group_id varchar);
sqlite>  create table profile_groups (profile_id integer, group_id varchar);
sqlite>  insert into user_groups values(1, 'group1');
sqlite>  insert into user_groups values(1, 'group2');
sqlite>  insert into user_groups values(1, 'group3');
sqlite>  insert into user_groups values(2, 'group1');
sqlite>  insert into user_groups values(2, 'group2');
sqlite>  insert into user_groups values(3, 'group4');
sqlite>  insert into user_groups values(4, 'group1');
sqlite>  insert into user_groups values(4, 'group5');
sqlite>  insert into user_groups values(4, 'group6');
sqlite> 
sqlite>  insert into profile_groups values (11, 'group1');
sqlite>  insert into profile_groups values (11, 'group2');
sqlite>  insert into profile_groups values (11, 'group3');
sqlite> 
sqlite>  insert into profile_groups values (21, 'group1');
sqlite>  insert into profile_groups values (21, 'group2');
sqlite> 
sqlite>  insert into profile_groups values (22, 'group4');
sqlite> 
sqlite>  insert into profile_groups values (23, 'group1');
sqlite>  insert into profile_groups values (23, 'group5');
sqlite>  insert into profile_groups values (23, 'group6');
sqlite>  select user_id, profile_id 
   ...>     from user_groups join profile_groups on 
   ...>     user_groups.group_id=profile_groups.group_id 
   ...>     group by user_id, profile_id
   ...>     having count(user_groups.group_id) = 
   ...>     (select count(*) from profile_groups as pg where 
   ...>     pg.profile_id=profile_groups.profile_id)
   ...>     and count(profile_groups.group_id) = (select count(*) from user_groups as ug where 
   ...>     ug.user_id=user_groups.user_id)
   ...>     ;
1|11
2|21
3|22
4|23

Upvotes: 4

OMG Ponies
OMG Ponies

Reputation: 332781

This will show you a list of users who are associated to profiles:

SELECT ug.user_id,
       pg.profile_id
  FROM USER_GROUPS ug
  JOIN PROFILE_GROUPS pg ON pg.group_id = ug.group_id

...while this will return a list of all the users, who may be associated to a profile. If they are not, the profile_id column will be null:

   SELECT ug.user_id,
          pg.profile_id
     FROM USER_GROUPS ug
LEFT JOIN PROFILE_GROUPS pg ON pg.group_id = ug.group_id

Keep in mind that because of the relationships being one user_id to many profiles, the user_id will likely be displayed multiple times, and possibly duplicates. For a non duplicated list of data, add the DISTINCT clause or define the GROUP BY clause. IE:

Using DISTINCT

   SELECT DISTINCT
          ug.user_id,
          pg.profile_id
     FROM USER_GROUPS ug
LEFT JOIN PROFILE_GROUPS pg ON pg.group_id = ug.group_id

Using GROUP BY

   SELECT ug.user_id,
          pg.profile_id
     FROM USER_GROUPS ug
LEFT JOIN PROFILE_GROUPS pg ON pg.group_id = ug.group_id
 GROUP BY ug.user_id, pg.profile_id

Upvotes: 1

hsz
hsz

Reputation: 152304

   SELECT ug.user_id, pg.profile_id
     FROM user_groups AS ug
LEFT JOIN profile_groups AS pg
       ON ug.group_id = pg.group_id

Upvotes: 2

Related Questions