考虑以下...这个例子假设互惠是通过在每个友谊中插入两行来建立的。但是,为简单起见,以下示例并未检查友谊是否得到回报!
DROP TABLE IF EXISTS friends;
CREATE TABLE friends
(initiator VARCHAR(12) NOT NULL
,reciprocator VARCHAR(12) NOT NULL
,PRIMARY KEY (initiator,reciprocator)
);
INSERT INTO friends VALUES
('Adam','Ed'),
('Ed','Adam'),
('Adam','Ben'),
('Ben','Adam'),
('Adam','Charlie'),
('Charlie','Adam'),
('Adam','Dan'),
('Dan','Adam'),
('Ed','Ben'),
('Ben','Ed'),
('Ben','Charlie'),
('Charlie','Ben'),
('Charlie','Dan'),
('Dan','Charlie'),
('Dan','Fred'),
('Fred','Dan'),
('Adam','Fred'),
('Fred','Adam');
要获得 Ben 的所有“朋友之友”的列表,我们可以这样做...
SELECT y.reciprocator
FROM friends x
JOIN friends y
ON y.initiator = x.reciprocator
AND y.reciprocator <> x.initiator
LEFT
JOIN friends z
ON z.reciprocator = y.reciprocator
AND z.initiator = x.initiator
WHERE x.initiator = 'Ben'
AND z.initiator IS NULL;
+--------------+
| reciprocator |
+--------------+
| Dan |
| Fred |
| Dan |
+--------------+
如您所见,因为 Dan 是 Adam 和 Charlie(Ben 的两个朋友)的朋友,所以他的名字出现了两次。
因此,要获取 DISTINCT 好友列表,只需包含 DISTINCT 运算符即可。
同样,要获取 Ben 不认识但至少是 Ben 的两个朋友的朋友的个人列表,我们可以这样做...
SELECT y.reciprocator
FROM friends x
LEFT
JOIN friends y
ON y.initiator = x.reciprocator
AND y.reciprocator <> x.initiator
LEFT
JOIN friends z
ON z.reciprocator = y.reciprocator
AND z.initiator = x.initiator
WHERE x.initiator = 'Ben'
AND z.initiator IS NULL
GROUP
BY y.reciprocator
HAVING COUNT(*) >= 2;
+--------------+
| reciprocator |
+--------------+
| Dan |
+--------------+
可能有几种方法可以处理这个问题的互惠方面,就像有几种方法可以处理互惠本身一样。
一种方法是将上面出现的friends 表替换为一个简单的子查询,例如
SELECT y.reciprocator
FROM (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) x
LEFT
JOIN (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) y
ON y.initiator = x.reciprocator
AND y.reciprocator <> x.initiator
LEFT
JOIN (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) z
ON z.reciprocator = y.reciprocator
AND z.initiator = x.initiator
WHERE x.initiator = 'Ben'
AND z.initiator IS NULL
GROUP
BY y.reciprocator
HAVING COUNT(*) >= 2;