Вопрос о присоединении к SQL - PullRequest
0 голосов
/ 23 декабря 2009

У меня есть следующие таблицы:

Таблица: группы пользователей (многие ко многим)

  • user_id (int)
  • group_id (varchar)

Таблица: profile_groups (многие ко многим)

  • profile_id (int)
  • group_id (varchar)

Итак, я хочу написать сценарий sql, чтобы узнать, какой профиль назначен каждому пользователю.

Таким образом, в конце должно быть только 2 столбца: user_id и profile_id.

Как бы я поступил так?

Редактировать: Это на самом деле намного сложнее, чем простое соединение.

1031 * Е.Г. *

Группы пользователей могут иметь следующие строки

  • 1 группа1
  • 1 группа2
  • 1 группа3
  • 2 группа1
  • 2 группа2
  • 3 группа4

и profile_groups могут иметь следующее:

  • 11 группа1
  • 11 группа2
  • 11 группа3
  • 21 группа1
  • 21 группа2
  • 22 группа4

Таким образом, результат должен быть

  • 1 11
  • 2 21
  • 3 22 * ​​1072 *

Каждый пользователь должен иметь только ОДИН профиль

Ответы [ 4 ]

4 голосов
/ 23 декабря 2009

Я только что видел такой вопрос на днях. Я думаю, что самая сложная часть здесь - вы ищете комбинации user_id / profile_id, где user_id имеет каждый group_id, который есть в profile_id, не больше и не меньше. Поэтому возьмите обычное объединение и добавьте некоторую корреляцию, чтобы подсчитать количество group_ids каждого профиля / пользователя и убедитесь, что они совпадают (это было отредактировано несколько раз):

 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
2 голосов
/ 23 декабря 2009
   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
1 голос
/ 23 декабря 2009

Это покажет вам список пользователей, которые связаны с профилями:

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
0 голосов
/ 23 декабря 2009

jjia6395, судя по комментариям под ответом zzzeek, ​​вы хотите использовать оператор ALL. Кстати, ваш вопрос ужасно неясен, редактирование не помогло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...