2013-05-29 2 views
0

Я пытаюсь расширить свои знания о MySQL и о том, как отношения могут работать между несколькими различными таблицами в базе данных. Я понимаю основные и внешние ключи и то, как они работают в таблицах.Таблица взаимосвязей в базе данных MySQL

У меня есть тестовая база данных Я играю с полным people, hats и отношениями между различными шляпами и людьми. Вот то, что я до сих пор в моей тестовой базе данных:

| Tables_in_test | 
+-----------------+ 
| hats   | 
| hats_collection | 
| people   | 
+-----------------+ 

Моя people таблица выглядит следующим образом:

+-----------+---------+ 
| person_id | fname | 
+-----------+---------+ 
|   1 | Sethen | 
|   2 | Michael | 
|   3 | Jazmine | 
+-----------+---------+ 

Моя hats таблица выглядит следующим образом:

+--------+----------+ 
| hat_id | hat  | 
+--------+----------+ 
|  1 | Awesome | 
|  2 | Kick Ass | 
|  3 | Bowler | 
|  4 | Fedora | 
+--------+----------+ 

И, наконец My hats_collection Таблица выглядит следующим образом:

+-----------+--------+ 
| person_id | hat_id | 
+-----------+--------+ 
|   2 |  1 | 
|   2 |  4 | 
|   3 |  2 | 
+-----------+--------+ 

По существу, я храню все разные шляпы, которые могут существовать в таблице головных уборов, и удерживая их отношение к разным людям в таблице hats_collection, которая использует только person_id и hat_id.

Хотя я уверен, как правильно настроить все эти таблицы и вставить данные, я не уверен, как записать запрос для отображения данных из таблицы hats_collection, чтобы отобразить имя пользователя и какую шляпу у них есть.

Вот то, что я до сих пор:

SELECT people.fname, hats.hat 
FROM people 
INNER JOIN hats 
INNER JOIN hats_collection 
ON hats_collection.person_id = people.person_id AND hats_collection.hat_id = hats.hat_id 
WHERE people.person_id = 1; 

Который возвращает пустой набор.

Мои вопросы таковы:

  1. Как бы я изменить свой запрос, чтобы получить правильные результаты которых люди имеют какие шляпы?
  2. Разве это так, я бы установил таблицы для чего-то вроде этого? Есть ли более простой/эффективный способ?

EDIT

Мои извинения, запрос я отправил работы. Он возвращал пустой набор, потому что у человека с идентификатором 1 нет шляп, но у него возник новый вопрос:

  1. Это лучший способ написать этот вопрос?

Мой вопрос о том, чтобы быть самым эффективным способом сделать это все еще стоит.

+1

Это известно как отношение «многие ко многим», а «hats_collection» - таблица перекрестных ссылок. Вы часто увидите имена таблиц, такие как 'people_hats' или' people_hats_xref'. – criticalfix

+1

@criticalfix Спасибо за эту информацию. Это обычная практика? – Sethen

+1

Да, это стандартная практика. Это правильный способ установить отношения. Ваша таблица xref может иметь составную PK, состоящую из двух столбцов FK, или вы можете иметь дополнительный столбец PK отдельно от двух столбцов FK. – criticalfix

ответ

1

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

SELECT people.fname, hats.hat 
FROM people 
INNER JOIN hats_collection 
    ON hats_collection.person_id = people.person_id 
INNER JOIN hats 
    ON hats_collection.hat_id = hats.hat_id 
WHERE people.person_id = 1; 

Таблицы разработаны в «нормальной/обычной практикой»

Теперь, если вы хотите, чтобы все люди, независимо, если у них есть шляпы или нет ... использовать LEFT JOIN вместо внутренней это выше.

+0

И использование 'INNER JOIN', как это, вполне приемлемо? Я имею в виду, используя его дважды, как у вас? – Sethen

+1

да, тот правый. –

+0

@ImreL Большое спасибо! – Sethen

1

Извлеките предложение WHERE в своем заявлении, чтобы показать людям свои шляпы. Согласно данным образца, person_id = 1 не имеет шляпы.

2

Лицо с id = 1 не имеет шляп, так что это нормально.

Если вы хотите отобразить лицо, даже если они не имеют какие-либо шляпы вы должны использовать LEFT JOIN вместо

SELECT people.fname, GROUP_CONCAT(hats.hat) AS hats 
    FROM people 
    LEFT JOIN hats_collection ON hats_collection.person_id = people.person_id 
    LEFT JOIN hats ON hats_collection.hat_id = hats.hat_id 
GROUP BY people.person_id; 

Обратите внимание, как я Переупорядоченная логически присоединился таблицами и поместить каждый соответствующее условие объединения своих собственных объединения таблиц ON части ,

+0

Что делает линия 'GROUP_CONCAT'? – Sethen

+0

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat он в основном генерирует отдельный список результатов, объединяющий все шляпы лиц в одну строку в результирующем наборе вместо того, чтобы иметь разные строки. – xQbert

+0

@xQbert Я вижу, он ограничивает результаты с помощью ',' в одной строке рядом с именем. Почему я должен делать это вместо того, чтобы иметь разные строки? Похоже, мне пришлось бы написать больше логики на стороне сервера, чтобы отделить их все так. – Sethen

Смежные вопросы