SQL朋友关系单向/双向系统

时间:2013-12-18 12:36:58

标签: sql

我正在与朋友创建一种社交网站,我有用户和朋友关系的表格

FRIENDS
id          iduser     idfriend
0             44           56
1             44          102
2             10           66
3             10           85
4             44           10
5             10           44
6             56           44

LOGIN
id         jmeno               email       isonline
44         john          john@gmail.com           1
10         joe           joe@yahoo.com            1
185        mark          mark@so.com              0

当用户连接他从服务器请求他的在线朋友时,我使用这个SQL命令

SELECT u.id, 
       jmeno, 
       email 
  FROM friends f 
       INNER JOIN login u 
           ON f.idfriend = u.id 
 WHERE f.iduser = 44 
       AND u.online =1

但我意识到这不是正确的解决方案,因为当用户44和用户10想成为朋友时,必须有两种关系:

    44  -  10 
    10  -  44

我只想从数据库中的一行中选择关系 所以在iduser和idfriend中找到id。现在我在这里使用这种单向关系sql。

2 个答案:

答案 0 :(得分:0)

有很多方法可以做到这一点。一种是在联接中进行or,以便您加入iduseridfriend

select
    u.*
from
    login u
    join friends f 
     on (u.id = f.iduser 
         and f.idfriend = 44)
     or (u.id = idfriend
         and f.iduser = 44)
where
  u.id != 44;

另一种方法是创建一个子查询,创建所有双向朋友关系列表,然后从中进行选择:

select
  *
from 
 (select
      iduser,
      u.*
  from
      friends f
      inner join login u on f.idfriend = u.id
  union
  select
      idfriend,
      u.*
  from
      friends f
      inner join login u on f.iduser = u.id) q
where
  q.iduser = 44
  and q.isonline = 1

您没有指定使用哪个数据库引擎 - 如果您使用的是支持CTE的数据库(例如Oracle或SQL Server),则子查询可以在CTE中完成。

第二种方法占用资源更多,但只需要对代码进行一次更改即可选择不同的ID。

所有三个查询都在此SQLFiddle中,但我删除了现有的双向友谊以说明逻辑。

答案 1 :(得分:0)

您当前的架构不一定是坏事。这就是我设计这种关系的方式。

Friends表是标准的交叉引用表。如果朋友关系被切断,你需要清理双方,但这很容易。它允许您加入一列id,并立即获得正确的idfriend。它也使得容易约束以保证唯一性。

你当前的架构也允许(10,44)意味着10想要成为44的朋友,但如果(44,10)不存在,那么也许44不想成为10的朋友。但是那么也许那样不是业务要求。

如果您希望(10,44)等同于(44,10),那么在创建关系时,您将不得不添加一个额外的查询以查看双方并确保现有关系不存在。

您可以在join子句中使用OR或使用UNION执行此操作。 Joe的代码对我来说很好看。您也可以在此处查看视图(或索引视图)。