SQL加入问题

时间:2009-12-23 01:11:35

标签: sql join

我有以下表格:

表:user_groups(多对多)

  • user_id(int)
  • group_id(varchar)

表:profile_groups(多对多)

  • profile_id(int)
  • group_id(varchar)

基本上,我想编写一个sql脚本来找出为每个用户分配的配置文件。

所以最后应该只有两列:user_idprofile_id

我将如何做到这一点?

编辑:它实际上比简单的连接复杂得多。

E.g。

User_groups可能包含以下行

  • 1 group1
  • 1 group2
  • 1 group3
  • 2 group1
  • 2 group2
  • 3 group4

和profile_groups可能包含以下内容:

  • 11 group1
  • 11 group2
  • 11 group3
  • 21 group1
  • 21 group2
  • 22 group4

所以结果应该是

  • 1 11
  • 2 21
  • 3 22

每个用户应该只有一个个人资料

4 个答案:

答案 0 :(得分:4)

前几天我刚看到这样的问题。我认为这里的难点在于您正在寻找user_id / profile_id组合,其中user_id具有profile_id具有的每个group_id,不多也不少。因此,采用通常的连接并添加一些相关性来计算每个配置文件/用户拥有的group_id的数量,并确保它们匹配(已经编辑了几次):

 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)
    ;

这是一个包含两个配置文件的运行,每个配置文件包含三个组,其中一个公共组和第四个配置文件中的新用户:

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

答案 1 :(得分:2)

   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

答案 2 :(得分:1)

这将显示与个人资料相关联的用户列表:

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

...虽然这将返回可能与个人资料相关联的所有用户的列表。如果不是,则profile_id列将为null

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

请记住,由于关系是一个user_id到多个配置文件,user_id可能会多次显示,并且可能会重复。对于非重复的数据列表,请添加DISTINCT子句或定义GROUP BY子句。 IE:

使用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

使用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

答案 3 :(得分:0)

jjia6395,从zzzeek的回答下面的评论判断,你想使用ALL运算符。 顺便说一下,你的问题非常不清楚,编辑没有帮助。