Присоединяйтесь к таблицам SQL - PullRequest
1 голос
/ 15 декабря 2010

Предположим, что в таблице "ab" у меня есть имена студентов, которые ладят с классом "a" и классом "b", то же самое у меня есть таблицы "ac" и "bc".Какой SQL-запрос я должен использовать для того, чтобы получить все возможные комбинации студентов, которые могут образовывать группы (например, «ладить друг с другом»)?И как я могу расширить это до п классов?Например: Джон из класса а ладит с Джен из класса b и Стефф из класса c, а Джен и Стефф ладят.Поэтому Джон, Джен и Стефф могут сформировать группу).

Ответы [ 4 ]

1 голос
/ 15 декабря 2010

Для этого я бы создал две таблицы: таблицу ученика (id, name, class) и таблицу отношений (student1, student2). Вы также можете добавить таблицу классов для времени, местоположения и т. Д. Класса.

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

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

Вот запрос, чтобы найти друзей друзей (fof):

SELECT fof_details.*
FROM relationships r
INNER JOIN relationships fof
ON r.student2 = fof.student1
INNER JOIN student fof_details
ON fof_details.id = fof.student2
WHERE r.student1 = '12';

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

http://openquery.com/blog/graph-engine-mkii

0 голосов
/ 15 декабря 2010

Во-первых, вы не хотите иметь таблицу для каждого класса.Вы собираете один и тот же тип информации в нескольких таблицах, и это обычно считается плохой практикой.Вы хотите «нормализовать» свои данные так, чтобы одни и те же данные существовали в одном месте.

Во-вторых, назовите ваши таблицы соответствующим образом, чтобы вы понимали, что вы на самом деле пытаетесь построить.Может быть, вы обобщаете, чтобы замаскировать свои намерения в отношении реальных реализаций, используя «ab» в вопросе, но если вы делаете это в своем реальном коде, это нанесет вам вред в долгосрочной перспективе.

Похожевам нужна таблица людей с именами и таблица друзей, где вы отслеживаете, кто с кем дружит:

create table people ( id int, name char(128) );
create table friends ( id int, person_id int, friend_id int );

Тогда вам просто нужен запрос для получения групп:

SELECT person.* FROM friends
INNER JOIN friends grp
        ON friends.friend_id = grp.person_id
INNER JOIN people person
        ON person.id = grp.friend_id
WHERE friends.person_id = 42;
0 голосов
/ 15 декабря 2010

Исходный запрос может быть удовлетворен кодом

select ab.a, ab.b, ac.c
from
ab inner join
bc on ab.b = bc.b inner join
ac on ac.a = ab.a and bc.c = ac.c

Переход к n классам будет постепенно усложняться, поскольку n = 4 будет тем же запросом с дополнительными тремя объединениями

inner join ad on ab.a = ad.a 
inner join bd on bd.b = ab.b and ad.d = bd.d
inner join cd on cd.c = ac.c and ad.d = cd.d 

2 класса требуют 1 таблицы и без объединений,
3 класса требует 3 таблицы и 2 объединения,
4 класса требуют 6 таблиц и 5 объединений

Таким образом, мы можем видеть, что это становится все более и более сложным, поскольку мы продолжаем

0 голосов
/ 15 декабря 2010

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

WITH ABC AS (SELECT AB.A, AB.B, AC.C FROM (SELECT * FROM AB
                        INNER JOIN BC 
                        ON AB.B=BC.B) 
         INNER JOIN AC 
         ON (AC.C=BC.C AND AB.A=AC.A))
SELECT STUDENT FROM (
    SELECT AB.B STUDENT FROM ABC WHERE AB.A='John'
    UNION
    SELECT AC.C STUDENT FROM ABC WHERE AB.A='John')
GROUP BY STUDENT

PS .: Написано быстро без какой-либо проверки синтаксиса, надеюсь, вы сможете заставить это работать:)

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