我有一个成员到成员连接的表.架构是member_id,friend_id,is_active.我想建立一个朋友朋友的成员联系列表.我不确定如何处理查询,更不用说以半优化的方式了解.
上面的表以一种方式工作,其中member_id和friend_id在另一个表上基本相同.在我的系统中,除了这一个表之外,这些id通常被称为member_id.例如,假设我的member_id是21.我的号码可以在无限量的其他行上作为member_id或friend_id,它或者基于谁最初发起了实际的友谊请求,我不希望冗余数据在哪里我有欺骗行基本上做同样的事情.
我想查询一下,我不仅可以建立一个学位水平(想想LinkedIn),而且我还可以确定一个人可能有多少共同的朋友正在展示(想想Facebook).这里的x因子是我之前提到的is_active列.此列可以是0或1.这是一个简单的tinyint列,可用作开/关开关.任何与1的朋友联系都是积极的友谊,而0正在等待.我需要将此查询基于我的活跃朋友和他们活跃的朋友等等.我的朋友们没有活跃的朋友都是我的活跃朋友.
如何构建这样的查询(即使我无法显示分离级别并且只能获得相互计数)?现在,我可以想到一些东西,但它涉及查询后查询一些嵌套在循环中,是的,我只是无法想象对我的服务器的整体性能或健康随着时间的推移有什么好处.
我的“朋友”表具有单向关系,因此我们确实存在重复项,即存储“1到2”和“2对1”.我也排除了is_active,因为实现很明显:
这是数据:
member_id friend_id
1 2
1 3
1 4
2 1
2 3
2 5
2 6
3 2
3 1
4 1
5 2
6 2
6 7
7 6
7 8
8 7
我们选择了会员1,我们要问的是7个朋友,7个朋友,朋友等等吗?计数0表示否,计数1表示是.
SELECT COUNT(*)
FROM friends f1
WHERE f1.member_id = 1
AND f1.friend_id = 7
如果不是,那么他们是朋友的朋友吗?
SELECT COUNT(*)
FROM friends f1
JOIN friends f2
ON f2.member_id = f1.friend_id
WHERE f1.member_id = 1
AND f2.friend_id = 7
如果没有,那么朋友的朋友呢?
SELECT COUNT(*)
FROM friends f1
JOIN friends f2
ON f2.member_id = f1.friend_id
JOIN friends f3
ON f3.member_id = f2.friend_id
WHERE f1.member_id = 1
AND f3.friend_id = 7
等等…
第三个查询将找到路径“1到2”,“2到6”和“6到7”,返回计数1.
每个查询都变得更加昂贵(由于连接数量较多),因此您可能希望在某些时候限制搜索.一个很酷的事情是这个搜索从两端向中间工作,这是一个简单的优化建议用于最短路径搜索.
以下是如何找到成员1的共同朋友推荐:
SELECT f2.friend_id
FROM friends f1
JOIN friends f2
ON f2.member_id = f1.friend_id
LEFT JOIN friends f3
ON f3.member_id = f1.member_id
AND f3.friend_id = f2.friend_id
WHERE f1.member_id = 1
AND f2.friend_id <> f1.member_id // Not ourself
AND f3.friend_id IS NULL // Not already a friend