Mysql 两次显示相同关系的Friendfeed

Mysql 两次显示相同关系的Friendfeed,mysql,sql,database,relational-database,Mysql,Sql,Database,Relational Database,我在facebook上建立一个feed系统只是为了好玩和训练,但我发现了一个有趣的问题。想象一下这个场景: 我是nr1、nr2和nr3的朋友。在我的数据库中,它也是一个用户,数据库中的nr4,我与之不是朋友。让我们假设nr1 befriend nr4,在这种情况下,我希望我的提要更新为nr1 is friend with nr4。这基本上不是很难做到,至少要让它工作起来,我对性能没有任何要求:P。 然后nr1和nr2成为朋友,但这与nr2和nr1是等价的,这就是我的问题 我的友谊数据库的工作方式

我在facebook上建立一个feed系统只是为了好玩和训练,但我发现了一个有趣的问题。想象一下这个场景:

我是nr1、nr2和nr3的朋友。在我的数据库中,它也是一个用户,数据库中的nr4,我与之不是朋友。让我们假设nr1 befriend nr4,在这种情况下,我希望我的提要更新为nr1 is friend with nr4。这基本上不是很难做到,至少要让它工作起来,我对性能没有任何要求:P。 然后nr1和nr2成为朋友,但这与nr2和nr1是等价的,这就是我的问题

我的友谊数据库的工作方式是一个友谊生成两个记录。我读过,这通常是最快的方法

友谊表:

用户id 朋友身份证 悬而未决的 最后的变化 用户表:

用户id 用户名 我想出了以下代码:

SELECT
    u1.user_id AS friend_id,
    u1.user_name SA friend_name,
    u2.user_id AS friends_friend_id,
    u2.user_name AS friends_friend_name
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = f1.friend_id
    && f1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN friendship AS f2
    ON u1.user_id = f2.user_id
    && f2.friend_pending = 0
JOIN users AS u2
    ON f2.friend_id = u2.user_id
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;
如果你听我的小故事,这就是我得到的。id=1不是我,是另一个用户

不幸的是,我想我还不够清楚。最后我想得到的是一个数组,其中每个元素都包含:

朋友身份证 朋友的名字 朋友\u朋友\u id 朋友\朋友\姓名 就像Edit3中的样本数据一样,除了我以前的名字可能会误导你。。 所以我的问题是,正如你所看到的编辑3,如果我的两个朋友成为朋友,我会为一段关系得到两行。我想得到的是:

friend_id  |  friend_name  |   friends_friend_id  |  friends_friend_name
    1             nr1                  2                   nr2     
    2             nr1                  1                   nr2
我希望我说得更清楚!谢谢

您是否尝试使用

SELECT DISTINCT

这在你的头脑中是一个棘手的问题,但是,试试这个:

SELECT  --Select your user details, and your direct friends details
    u1.user_id UserId,
    u1.user_name UserName,
    u2.user_id FriendsUserId,
    u2.user_name FriendsUserName
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN users AS u2
    ON f1.friend_id = u2.user_id
JOIN friendship AS f2
    ON f1.friend_id = f2.userid
    && f2.friend_pending = 0
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;
UNION 
SELECT  --Select your user details, and your friends friends details
    u3.user_id UserId,
    u3.user_name UserName,
    u4.user_id FriendsUserId,
    u4.user_name FriendsUserName
FROM users AS u3
JOIN friendship AS f3
    ON u3.user_id = {$user_id}
    && f3.friend_pending = 0
JOIN friendship AS f4
    ON f3.friend_id = f4.user_id
    && f4.friend_pending = 0 
JOIN users AS u4
    ON f3.friend_id = u4.user_id
WHERE TIMESTAMPDIFF(SECOND, f4.lastchange, '{$last_login}' ) < 0;
假设结果与我想的一样,工会应该将重复项过滤为u1。用户id应该始终是您的用户id。

试试看

SELECT     
    u1.user_id AS friend_id,     
    u1.user_name SA friend_name,     
    u2.user_id AS friends_friend_id,     
    u2.user_name AS friends_friend_name 
FROM users AS u1 
JOIN friendship AS f1     
    ON u1.user_id = f1.friend_id     
     && f1.user_id = {$user_id}     
     && f1.friend_pending = 0 
JOIN friendship AS f2     
    ON u1.user_id = f2.user_id     
     && f1.user_id <> f2.friend_id 
     && f2.friend_pending = 0 
JOIN users AS u2     
     ON f2.friend_id = u2.user_id 
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0; 

因此,在我看来,您的要求不完整,在friend feed中,如果nr2和nr1彼此成为朋友,您想:

看到一些东西说你的共同朋友nr2和nr1彼此成为朋友! 看到什么说你的朋友nr2和nr1成了朋友!根据谁第一次接触到友谊。 情景1

您需要另一个连接来检查您朋友的朋友是否也在您的朋友中,如果是,则返回一个名为AlsmyFriend的布尔列。然后,如果AlsmyFriend为1,则返回一个您共同的朋友彼此成为朋友,否则返回一个正常的您的朋友与新朋友成为朋友

或者,您也可以在代码中执行此操作,只需检查您的朋友的ID是否在您的朋友ID数组中,然后根据该ID翻转您的提要语句即可

情景2

向友谊表*primary\u mover*中添加一列,并将该值设置为发起友谊的*user\u id*。查找朋友的朋友时,请筛选*其中主移动器=用户id*,以仅获取双边关系中的1个

作为一个简单的度量,您可以简单地添加一个过滤器,在朋友的朋友ID大于我的朋友ID的情况下,只提取朋友的朋友:

SELECT
    u1.user_id AS friend_id,
    u1.user_name SA friend_name,
    u2.user_id AS friends_friend_id,
    u2.user_name AS friends_friend_name
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = f1.friend_id
    && f1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN friendship AS f2
    ON u1.user_id = f2.user_id
    && f2.friend_pending = 0
    && f2.friend_id > f2.user_id -- pulls nr1 befriending nr2, not nr2 befriending nr1
JOIN users AS u2
    ON f2.friend_id = u2.user_id
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;

我想到了这一点,但请注意,选择中有u1和u2。这意味着DISTINCT将无法解决,因为双重关系将倒退。事实上不会,但在我的情况下,这真的可能吗?因为我有不同的列被交换。u1.user\u id与u2.user\u id交换。user\u id你能发布一些示例数据和输出吗,这有点难想象发生了什么。user\u id,friend\u id是唯一的密钥吗?您可能有重复的数据。是的,我使用的是唯一的密钥,所以这不会是一个问题。好的。。隐马尔可夫模型。。恐怕它根本不起作用:不管是工会还是全体工会。第一个只是给了我和我的朋友是朋友的用户和我的朋友是朋友的用户。另一方面,工会给了我一个长长的名单,上面有我的朋友和朋友。但你确实给了我一些想法,我要尝试一下!如果我解决了,我会发布一个答案!我以为那就是你想要的?自上次登录后与其他人成为朋友的所有我的朋友-选择1。然后选择我的朋友和我的朋友已经成为朋友的用户ID和用户名-选择2?不管怎么说,希望你能解决……嗯,该死的,我完全明白在我写了这些之后你会怎么想。我会更新课文,尽量让自己更清楚。不幸的是,我的想法并没有把我带到任何地方。UNION ALL并没有过滤掉预先选择的记录。这就是为什么它比UNION更快。我试过了,但没有成功:如果我没有完全错的话,那是因为它只检查当前的f1.user\u id,由于我使用了唯一的键,它将总是不同的,因此我得到了与不使用相同的答案
SELECT
    u1.user_id AS friend_id,
    u1.user_name SA friend_name,
    u2.user_id AS friends_friend_id,
    u2.user_name AS friends_friend_name
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = f1.friend_id
    && f1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN friendship AS f2
    ON u1.user_id = f2.user_id
    && f2.friend_pending = 0
    && f2.friend_id > f2.user_id -- pulls nr1 befriending nr2, not nr2 befriending nr1
JOIN users AS u2
    ON f2.friend_id = u2.user_id
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;