23

我是 SQL 的新手,我首先尝试尽可能多地学习,因为我正在设计我必须使用一段时间的数据库,所以这很困难,所以我想确保我做对了。我学习了多对多桥接表的基础知识,但是如果这两个字段是相同的类型怎么办?假设一个拥有数千名用户的社交网络,您将如何创建一个表格来跟踪谁是谁的朋友?如果有关于每个关系的附加数据怎么办,比如......“约会朋友”。知道会有诸如“显示在 dateY 和 dateZ 之间的 userX 的所有朋友”之类的查询。我的数据库会有这样的几种情况,我想不出一种有效的方法来做到这一点。因为它对我来说很多,

4

4 回答 4

35

Create a User table then a Relationships table where you store the id of the two friend and any kind of information about their relationship.

SQL diagram

SQL diagram

MySQL code

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 selection

After you fill up the tables with data, you can create your SQL SELECT query to get all of your friends. Your friends are those whose id is in one side side while your id is in the other side. You check both sides for your id so you don't need to store relationships twice. Also you have to exclude your id, because you can't be your own friend (in a normal, healthy world).

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;

Where $myid, $startdate and $enddate can be PHP variables so in double quotes you can pass this code directly to your database.

于 2013-09-04T00:24:30.353 回答
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
于 2013-09-04T00:14:21.977 回答
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';

您可能会注意到,如果您不关心交朋友的日期,则不需要到JOINfriendship中,因为连接已经共享friendship_id密钥。任何此类查询的本质都是JOINbetweenconn_Aconn_Bon conn_A.friendship_id = conn_B.friendship_id

于 2013-09-04T00:17:45.257 回答
2

您应该使用两个用户的 ID 作为关系表中的 PRIMARY KEY(即使不是双向的关系也是唯一的)。类似的东西

CREATE TABLE Users( idint(9) NOT NULL AUTO_INCREMENT,
PRIMARY KEY ( id));

CREATE TABLE Relationships( id1int(9) NOT NULL, id2int(9) NOT NULL, friendedTIMESTAMP NOT NULL, PRIMARY KEY ( id1, id2));

请注意:

  • id1 和 id2 参考用户表(上面的代码非常简化)
  • 即使关系不是“双向”,您也可以认为如果您有 id1 - id2 似乎 id1 用户将 id2 用户添加为朋友,但不一定相反 - 那么 id2 用户可以将 id1 用户添加为朋友 - 在关系表你可以有这些可能的组合:
    • id1-id2,(只有1加2为好友)
    • id2-id1, (only2加1为好友)
    • id1-id2 和 id2-id1 (两者 - 这意味着关系表中的 2 行,并且都是相互的朋友)
于 2015-12-20T05:36:39.760 回答