Некоторая помощь в запросе третьей нормальной формы - PullRequest
2 голосов
/ 20 марта 2012

У меня есть три таблицы.Один из них состоит из людей, второй - из собраний и третий - из посещаемости (связывает людей с собраниями).Подробно таблицы приведены ниже:

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

. Помощь с объяснением была бы чрезвычайно полезна.

Ответы [ 3 ]

3 голосов
/ 20 марта 2012

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

Поскольку у вас есть взаимные отношения, ваши первоначальные отчеты будут иметь избыточность, если вы не предпримете шаги для их удаления. Под этим я подразумеваю, что если Фред встречает Мэри на встрече № 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 |
+------+-----------+

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

1 голос
/ 20 марта 2012
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 голосов
/ 20 марта 2012

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

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, чтобы избежать перечисления одинаковыхвстретиться дважды

...