自我加入多对多的关系

C.J*_*.J. 11 sql sql-server

根据以下样本数据,假设Julie(1)有朋友Adam,David,John(2,3,4).亚当(2)有朋友朱莉,大卫,约翰(1,3,4).

ID  Name
1   Julie
2   Adam
3   David
4   John
5   Sam
Run Code Online (Sandbox Code Playgroud)

这使得一个表中的自连接和多对多关系成为可能.

除了上述问题之外,Julie(1)还说Sam(5)是朋友,从技术上和实际上讲,Sam(5)现在也是Julie(1)的朋友.这使得事情变得更加复杂,因为这种关系是双向的.

所以我想知道:

  1. 我该如何设计数据库?
  2. 如何进行将返回每个用户的所有朋友的查询?

谢谢!

Bri*_*lia 8

示例数据:

PEOPLE

PERS_ID     PERS_NAME
1           Julie
2           Adam
3           David
4           John
5           Sam

FRIENDSHIPS

PERS_ID     FRIEND_ID
1           2
1           3
1           4
2           3
2           4
Run Code Online (Sandbox Code Playgroud)

查询:

select people.pers_id    as person,
       people.pers_name  as person_name,
       peoplef.pers_id   as friend_id,
       peoplef.pers_name as friend_name
  from people
  join friendships
    on people.pers_id = friendships.pers_id
    or people.pers_id = friendships.friend_id
  join people peoplef
    on (peoplef.pers_id = friendships.pers_id and
       peoplef.pers_id <> people.pers_id)
    or (peoplef.pers_id = friendships.friend_id and
       peoplef.pers_id <> people.pers_id)
 order by 2, 4
Run Code Online (Sandbox Code Playgroud)

SQL小提琴演示:http://sqlfiddle.com/#!2/97b41/6/0

无论您是否在友谊表上记录两个方向,这都将有效.


Jan*_*ley 5

几乎与其他人同意。您需要一个链接表。我将提供更多详细信息。一些键和索引示例以及您想要的查询(双向)。

    CREATE TABLE dbo.tblUser 
(
    ID int identity(0,1),
    name varchar(20)
    CONSTRAINT PK_tblUser PRIMARY KEY (ID)
)

-- Many to many link table with FKs
CREATE TABLE dbo.tblFriend 
(
    ID1 int not null constraint FK_tblUser_ID1 foreign key references dbo.tblUser(ID), 
    ID2 int not null constraint FK_tblUser_ID2 foreign key references dbo.tblUser(ID)
    CONSTRAINT PK_tblFriend PRIMARY KEY (ID1, ID2)
)

-- Add index (So you can get an index seek if using ID2)
CREATE INDEX IX_tblFriend_ID2 ON dbo.tblFriend (ID2)

-- Test data
INSERT INTO dbo.tblUser(name)
VALUES ('Julie'),('Adam'),('David'),('John'),('Sam');

Insert INTO dbo.tblFriend (ID1, ID2) 
values(0, 1),(2, 0)


-- Get bi-directional friend to friend relationships
SELECT U1.Name as 'User1', U2.Name as 'User2' FROM dbo.tblFriend F 
    INNER JOIN dbo.tblUser U1 ON U1.ID = F.ID1
    INNER JOIN dbo.tblUser U2 ON U2.ID = F.ID2

UNION

SELECT U2.Name as 'User1', U1.Name as 'User2' FROM dbo.tblFriend F 
    INNER JOIN dbo.tblUser U1 ON U1.ID = F.ID1
    INNER JOIN dbo.tblUser U2 ON U2.ID = F.ID2

ORDER BY User1, User2
Run Code Online (Sandbox Code Playgroud)


Riz*_*Riz 4

一种方法是创建第二个表来存储人员 ID 和朋友 ID。在这种情况下,请考虑下表。

CREATE TABLE User 
    (
     id int auto_increment primary key, 
     name varchar(20)
    );

CREATE TABLE Friend 
    (
     user_id int , 
     friend_id int      
    );

INSERT INTO User
(name)
VALUES
('Julie'),
('Adam'),
('David'),
('John'),
('Sam');

Insert INTO Friend
(user_id, friend_id)
values(1, 5),
(3, 1);
Run Code Online (Sandbox Code Playgroud)

现在Friend表将存储user_id和他/她的friend_id。要获取特定用户的好友列表,您可以在这两列中搜索匹配的 id。以下是示例查询。

-- Get Friends of Julie
select 1 AS user_id, IF(user_id = 1, friend_id, user_id) AS friend_id
FROM Friend
WHERE user_id=1 OR friend_id=1;

-- Get Friends of David
select 3 AS user_id, IF(user_id = 3, friend_id, user_id) AS friend_id
FROM Friend
WHERE user_id=3 OR friend_id=3
Run Code Online (Sandbox Code Playgroud)

我希望你对此有所了解并可以尝试一下。