避免好友数据冗余 table

Avoid data redundancy in a friends table

我正在尝试设计一个非常简单的 table 来存储社区中朋友的数据。

所以我分别存储了2个朋友的userId

目标

用户想要加载 his/her 好友列表。

t_friends 选项一:

查询

SELECT * FROM t_friend WHRE user_id = 10 

10 是当前 userId 正在查找他的好友列表的用户,他有 1 个好友 userId(20)

这样 userId (10) 可以找到他的朋友 (20) 但是如果 userId(20) 正在寻找他的朋友呢? 查询加上 userId.

这让我想到了另一个包含冗余数据的设计:

t_friends选项2:

userId (10) 现在加载:

SELECT * FROM t_friend WHRE user_id=10

类似于 userId(20) 的查询将是:

SELECT * FROM t_friend WHRE user_id=20

但是冗余呢?这导致我使用 table 设计选项 1:

进行查询
SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10

我觉得有一种更聪明的方法可以解决这个问题。您对这种结构有任何经验吗?

谢谢

您可能需要使用以下查询来验证您的用户是否已经不是另一个人的朋友:

INSERT INTO t_friend (userId, friendId)
SELECT 10, 20
WHERE NOT EXISTS (  SELECT userId
                    FROM t_friend 
                    WHERE userId = 20
                    AND friendId = 10)

感谢这个关于冗余验证的(法语)话题 here

我认为这是存储关系数据的唯一方法。当您存储关系时,尝试将最小值存储为 userId,将最大值存储为 friendId。使这两个值完全唯一,您将不会得到任何重复值。当您搜索用户时,请使用如下内容

SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10

添加字段friendship_key:

ALTER TABLE t_friend ADD friendship_key decimal(22,11);

CREATE UNIQUE INDEX friendship_key_unique ON t_friend (friendship_key);

和php部分:

$friends = [$userId, $friendId];
$key = min($friends).'.'.max($friends);

$q = "SELECT * FROM t_friend WHERE friendship_key = ".$key;

插入:

$friends = [$userId, $friendId];
$key = min($friends).'.'.max($friends);

$q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $userId, $friendId]).")";

我没有使用 VARCHAR 作为友谊键,而是使用 decimal 来最小化关系键的数据。

为了简单起见,只需创建函数:

function insertFriendship($user1, $user2) {
    $key = min([$user1, $user2]).'.'.max([$user1, $user2]);
    $q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $user1, $user2]).")";
    mysql_query($q);
}

function getFriendsOf($user) {
    $q = "SELECT * FROM t_friends WHERE ".$user." IN (userId, friendId)";
    return mysql_query($q);
}

function areFriends($user1, $user2) {
    $key = min([$user1, $user2]).'.'.max([$user1, $user2]);
    $q = "SELECT 1 FROM t_friends WHERE friendship_key = ".$key." LIMIT 1";
    $q = mysql_query($q);
    return (mysql_num_rows($q)>0);
}