我是SQL的新手,我正在首先尝试尽可能多地学习,因为我正在编码,这很难,因为我正在设计数据库,我将不得不忍受所以我想确保我做得对。我学习了多对多桥接表的基础知识,但是如果这两个字段是相同的类型呢?让我们说一个拥有数千名用户的社交网络,你会如何创建一个表来跟踪谁是谁的朋友?如果有关于每个关系的其他数据怎么办,比如......“约会对象”。知道会有“在dateY和dateZ之间显示所有userX朋友”之类的查询。我的数据库有几种这样的情况,我无法找到一种有效的方法。既然它对我来说很重要,我认为其他人已经找到了设计表格的最佳方法,对吗?
答案 0 :(得分:33)
创建一个User
表,然后创建一个Relationships
表,您可以在其中存储两个朋友的id
以及有关他们之间关系的任何信息。
CREATE TABLE `Users` (
`id` TINYINT NOT NULL AUTO_INCREMENT DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `Relationships` (
`id` TINYINT NOT NULL AUTO_INCREMENT DEFAULT NULL,
`userid` TINYINT NULL DEFAULT NULL,
`friendid` TINYINT NULL DEFAULT NULL,
`friended` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
ALTER TABLE `Relationships` ADD FOREIGN KEY (userid) REFERENCES `Users` (`id`);
ALTER TABLE `Relationships` ADD FOREIGN KEY (friendid) REFERENCES `Users` (`id`);
使用数据填充表后,您可以创建SQL SELECT
查询以获取所有朋友。你的朋友是那些id
在一边而你的身份在另一边的人。您检查id
的双方,这样您就不需要存储两次关系。此外,您必须排除id
,因为您不能成为自己的朋友(在正常,健康的世界中)。
SELECT *
FROM Users u
INNER JOIN Relationships r ON u.id = r.userid
INNER JOIN Relationships r ON u.id = r.friendid
WHERE
(r.userid = $myid OR r.friendid = $myid)
AND r.friended >= $startdate
AND r.friended <= $enddate
AND u.id != $myid;
$myid
,$startdate
和$enddate
可以是PHP变量,因此在双引号中,您可以将此代码直接传递给数据库。
答案 1 :(得分:4)
单个链接表就足够了,如下所示:
People( PersonId bigint, Name nvarchar, etc )
Friends( FromPersonId bigint, ToPersonId bigint, DateAdded datetime )
示例查询:
SELECT
People.Name
FROM
Friends
INNER JOIN People ON Friends.FromPersonId = People.PersonId
WHERE
Friends.ToPersonId = @myPersonId
SELECT
People.Name
FROM
Friends
INNER JOIN People ON Friends.FromPersonId = People.PersonId
WHERE
Friends.ToPersonId = @myPersonId
AND
Friends.DateAdded >= @startDate
AND
Friends.DateAdded <= @endDate
答案 2 :(得分:4)
模型
可以选择延伸三张桌子的模型。您将拥有明显的表user
,其中包含所有用户的详细信息(姓名,出生日期......)。
CREATE TABLE `user` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45),
`dob` DATE,
PRIMARY KEY (`id`)
);
其次,用户的表connection
可以包含授予连接的权限(此连接可以查看我的相册),更重要的是,它将引用表friendship
。我们之间需要表connection
,因为一个用户可以连接成许多友谊。
CREATE TABLE `connection` (
`id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
`friendship_id` INT NOT NULL,
`privilege_mask` TINYINT,
PRIMARY KEY (`id`)
);
friendship
反过来可以包括共享细节,例如建立这种友谊时。 连接到同一 friendship
的用户。
CREATE TABLE `friendship` (
`id` INT NOT NULL AUTO_INCREMENT,
`met_first_time` DATE,
PRIMARY KEY (`id`)
);
这种方式比目前发布的其他解决方案更加真实,因为它避免了方向性(无法交流的友谊 - 这应该不存在!),但这会更多一些工作实施。
查询好友
应该查询朋友姓名的示例可能是(虽然未经过测试):
SELECT B.name FROM user A
INNER JOIN connection conn_A ON conn_A.user_id = A.id
INNER JOIN connection conn_B ON conn_A.friendship_id = conn_B.friendship_id
INNER JOIN user B ON conn_B.user_id = B.id
INNER JOIN friendship ON friendship.id = conn_A.friendship_id
WHERE A.name = 'Dan' AND A.id <> B.id AND
friendship.met_first_time BETWEEN '2013-4-1' AND '2013-6-30';
您可能会注意到,如果您不关心结交朋友的日期,则无需JOIN
到friendship
表,因为连接已共享friendship_id
个键。任何此类查询的实质都是JOIN
上conn_A
和conn_B
之间的conn_A.friendship_id = conn_B.friendship_id
。
答案 3 :(得分:2)
您应该在关系表中使用两个用户的ID作为PRIMARY KEY(即使不是双向的,该关系也是唯一的)。像这样的东西
CREATE TABLE
Users
(id
int(9)NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id
));CREATE TABLE
Relationships
(id1
int(9)NOT NULL,id2
int(9) NOT NULL,friended
TIMESTAMP NOT NULL,PRIMARY KEY(id1
,id2
));
请注意: