Неожиданные результаты после присоединения к другой таблице - PullRequest
1 голос
/ 23 сентября 2011

Я использую три таблицы, чтобы добраться до конечного результата.Они называются project_board_members, users и project_team.

Это запрос:

SELECT `project_board_members`.`member_id`,
       `users`.`name`,
       `users`.`surname`,
       `users`.`country`,
       `project_team`.`tasks_completed`
FROM `project_board_members`
JOIN `users`
    ON (`users`.`id` = `project_board_members`.`member_id`)
JOIN `project_team`
    ON (`project_team`.`user_id` = `project_board_members`.`member_id`)
WHERE `project_board_members`.`project_id` = '5'

Вы можете игнорировать последнюю строку, потому что она просто указывает на проект, который яusing.

Таблица project_board_members содержит три записи и имеет следующую структуру:

  • id,
  • member_id,
  • project_id,
  • created_at;

Мне нужно получить member_id из этой таблицы.Затем я присоединяюсь к таблице users, чтобы получить name, surname и country.Нет проблем.Все работает!:)

После этого мне нужно было получить tasks_completed для каждого пользователя.Это хранится в таблице project_team.Большой неожиданностью является то, что мне вернули четыре записи, а большая проблема в том, что в таблице project_board_members всего три записи.

Почему это так?Спасибо за совет!

Ответы [ 3 ]

1 голос
/ 23 сентября 2011

Таблица project_board_members представляет то, что в мире моделирования Entity-Relationship называется «ассоциативной сущностью».Он существует для реализации отношения «многие ко многим» (в данном случае между проектом и пользовательскими объектами. Таким образом, это зависимый объект, то есть существование его экземпляраосновывается на существовании экземпляра каждого из объектов, на которые он ссылается (пользователя и проекта).

В результате столбцы содержат внешние ключи, относящиеся к этим объектам (member_id и project_id) должен быть частью или всем первичным ключом.

Обычно экземпляры ассоциативного объекта являются уникальными WRT объектами, к которым он относится. В вашем случае определения отношений будут такими:

  • Каждый пользователь сидит на доске 0-ко-многим проектам;
  • Плата каждого проекта состоит из 0-ко-многим пользователям

, то естьскажем, что конкретный пользователь может не входить в правление определенного проекта более одного раза. Единственная причина добавления других столбцов (например, столбца id) к первичному ключу состоит в том, еслиОтношение пользователь: проект не является уникальным.

Для соблюдения этого правила - пользователь может один раз сесть на доску определенного проекта - схема таблицы должна выглядеть следующим образом:

create table project_board_member
(
  member_id  int not null foreign key references user    ( user_id ) ,
  project_Id int not null foreign key references project ( project_id ) ,
  created_at ...

  ...

  primary key ( member_id , project_id ) ,
)
}

Столбец id является лишним.

1 голос
/ 23 сентября 2011

Соединение SQL создает результирующий набор, который содержит одну строку для каждой комбинации левой и правой таблиц, которая соответствует условиям объединения. Не видя данных или немного больше информации, трудно сказать, что именно не так, как вы ожидаете, но я предполагаю, что это одно из следующего:

1) У вас есть две записи в project_team с одинаковым идентификатором пользователя.

2) Ваши записи в project_team хранят и user_id, и project_id, и вам нужно присоединиться к ним обоим, а не просто к user_id.

0 голосов
/ 23 сентября 2011

В целях отладки выполните

SELECT GROUP_CONCAT(pbm.member_id) AS member_ids,
       GROUP_CONCAT(u.name) as names,
       GROUP_CONCAT(u.surname) as surnames,
       GROUP_CONCAT(u.country) as countries,
       GROUP_CONCAT(pt.tasks_completed) as tasks
FROM project_board_members pbm
JOIN users u
    ON (u.id = pbm.member_id)
JOIN project_team pt
    ON (pt.user_id = pbm.member_id)
WHERE pbm.project_id = '5'
GROUP BY pbm.member_id

Все поля, в которых перечислены несколько записей в результате, приводят к путанице в количестве строк в наборе результатов.

Исправить, что вы можете сделать:

SELECT pbm.member_id
       u.name,
       u.surname,
       u.country,
       pt.tasks_completed
FROM (SELECT 
        p.project_id, p.member_id 
        FROM project_board_members p 
        WHERE p.project_id = '5'
      LIMIT 1
     ) AS pbm
JOIN users u
    ON (u.id = pbm.member_id)
JOIN project_team pt
    ON (pt.user_id = pbm.member_id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...