2012-03-20 4 views
2

У меня есть три таблицы. Один из людей, второй из совещаний и третий посещаемости (связывание людей с встречами). Более подробно, таблицы следующим образом:Некоторая помощь, запрашивающая третью нормальную форму

CREATE TABLE IF NOT EXISTS `people` (
    `id` int(255) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `icon` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 


CREATE TABLE IF NOT EXISTS `attend` (
    `people_id` int(255) NOT NULL, 
    `meeting_id` int(255) NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 


CREATE TABLE IF NOT EXISTS `meeting` (
    `id` int(255) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

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

Я только был в состоянии работать, как залезть в одном направлении с SQL

SELECT people.name, meeting.id FROM people LEFT JOIN attend ON people_id = people.id LEFT JOIN meeting ON meeting_id = meeting.id 

Помощь с объяснением будет оценен чрезвычайно.

+0

Просьба перечислить структуру вашей таблицы вместе с запросом, который вы пробовали до сих пор. –

+0

Какой формат лучше всего будет отображать в структуре таблицы? – Gausie

+0

Ну, самое лучшее, что ИМХО должно было бы перечислить ваши инструкции «create table». Таким образом, мы получаем все ограничения и т. Д. –

ответ

1
select distinct p1.name, p2.name 
from people p1, people p2, attend a1, attend a2, meeting m 
where p1.id = a1.people_id 
    and p2.id = a2.people_id 
    and a1.meeting_id = m.id 
    and a2.meeting_id = m.id 
    and p1.id <> p2.id 

или обходя стол на тему:

select distinct p1.name, p2.name 
from people p1, people p2, attend a1, attend a2 
where p1.id = a1.people_id 
    and p2.id = a2.people_id 
    and a1.meeting_id = a2.meeting_id 
    and p1.id <> p2.id 
+0

Фантастический! Я приблизился к этому, но никогда не включался в p1 <> p2! – Gausie

0

Пожалуйста, попробуйте следующее

select p1.name as name1, p2.name as name2 
from attend a1 
inner join attend a2 
    on a2.meeting_id = a1.meeting_id 
    and a2.people_id > a1.people_id 
inner join people p1 
    on p1.id = a1.people_id 
inner join people p2 
    on p2.id = a2.people_id 

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

3

Ваш дизайн стола - goo d - вы сможете делать все, что захотите, когда вы храните информацию таким образом.

Поскольку у вас есть взаимные отношения, ваши первоначальные отчеты будут иметь избыточность, если вы не предпримете шаги по их удалению. Под этим я подразумеваю, что если Фред встречает Мэри на встрече №1, то Мэри встречает Фреда на том же заседании. Таким образом, первое решение, ниже, перечисляет все дважды - но это полезно, если вы хотите, чтобы быть в состоянии найти кого-либо в вашем список лица и список, который они встретились:

SELECT distinct p1.name, 'met', p2.name, 'at', a1.meeting_id 
FROM people as p1 
    JOIN attend as a1 on a1.people_id = p1.id 
    JOIN attend as a2 on a2.meeting_id = a1.meeting_id 
    JOIN people as p2 on p2.id = a2.people_id 
where p1.id <> p2.id 
order by a1.meeting_id; 

+------+-----+------+----+------------+ 
| name | met | name | at | meeting_id | 
+------+-----+------+----+------------+ 
| Mary | met | Fred | at |   1 | 
| Fred | met | Mary | at |   1 | 
| Eric | met | Mary | at |   2 | 
| Mary | met | Eric | at |   2 | 
+------+-----+------+----+------------+ 

Вы видите, что я имею в виду списка все дважды. Если вы сортируете либо p1.name, либо p2.name, вы объединяете людей, чтобы все, с кем встречались «Мэри», были вместе в списке.

Но вы можете делать другие вещи, в зависимости от того, как программа, использующая ваши запросы, будет работать.

SELECT p.name, (SELECT group_concat(name) 
    FROM people as p1 
    JOIN attend as a1 on a1.people_id = p1.id 
    JOIN attend as a2 on a2.meeting_id = a1.meeting_id 
    WHERE a2.people_id = p.id 
     AND p.id <> p1.id) 
FROM people as p 
ORDER by p.name; 

+------+-----------+ 
| name | People | 
+------+-----------+ 
| Eric | Mary  | 
| Fred | Mary  | 
| Mary | Fred,Eric | 
+------+-----------+ 

Это менее эффективно (которые могут иметь или не иметь значения для вас), но вы получите список для каждого человека, кто они встретились. Вы можете развернуть этот запрос, чтобы перечислить собрания, на которых они встречались, и т. Д.

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