类似于 Facebook 的好友列表。每个用户都可以查看用户的个人资料并将他们添加到他们的部落中。每个用户都是一个部落的首领
好的,所以你有一张User
桌子,而且还需要一张Tribe
桌子。
那么您描述的关系是 a chief-of
,它是一对一的(一个用户可以是一个部落的酋长;一个部落只有一个酋长),因此您可以将其存储在User
(chief_of: Tribe) 或Tribe
(主管:用户)。
CREATE TABLE User ...
chief_of integer
在这里,chief_of
可能是一个外键,因此如果您删除一个部落,相关元组将chief_of
设置为 NULL(用户不能成为不再存在的部落的首领)。
成员资格有点复杂,因为一个用户可以属于多个部落,而一个部落将有多个成员。
这是一个多对多的关系,通常通过一个包含密钥对的表来完成:
CREATE TABLE member_of (
user_id integer,
tribe_id integer
);
这两个字段都是外键的自然候选者。在这里Authors
,您可以使用and找到类似的实现Books
。
为了表明 Bob 是洞穴熊氏族的成员,您检索 Bob 和 Bears 的 id,并在 中插入一个元组member_of
。
要检索氏族的所有成员,您可以使用 JOIN:
SELECT Users.* FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');
我认为 MySQL 中 ON 的较短版本是USING(user_id)
(这意味着两个表都有一个相同名称的相同列),但在我看来ON
更清晰。
您还可以检索虚拟“is_chief”列:
SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');
chief_of
属性等于部落 id的一个用户将is_chief
设置为 TRUE,即等于 1,所以
SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear')
ORDER BY (chief_of = tribe_id) DESC, user_name;
将按字母顺序检索用户,除了首席,如果存在,将首先出现。
至于接受加入部落,这确定了三种状态:用户不在部落中,用户在部落中,用户被要求加入部落。前两张其实是两张同属性的脸member_of
。所以很自然我们可能会创建一个新属性并调用它wants_in
。它将映射到与 相同的表member_of
。
酋长可以检索wants_in
其tribe_id
等于他自己的所有元组chief_of
(因此,如果它是 NULL,这意味着他不是酋长,这将自动返回nothing)。然后他可能会将其视为带有用户名的复选框表。当他批准加入时,对于每个批准,您都删除元组wants_in
并将其放入member_of
.
或者您可能决定“成员资格”本身就是一个状态,因此您有一个更复杂的连接表
user_id,
tribe_id,
status
status
比如说,可能在哪里
- 什么都没有(没有 (U, T, ?) 元组):用户 U 和部落 T 彼此不认识
- 100:用户U是部落T的正式成员
- -1:部落 T 已决定 U 不是成员,甚至不能要求成为成员。
- 0:用户 U 想成为 T 的成员
- 1-99:用户U是试用(学徒)会员。