自行加入以结交朋友的朋友 SQL
Self join to get friends of friend in SQL
我有一个 friends
table 如下
+------+--------+
| Name | Friend |
+------+--------+
| A | B |
| B | C |
| D | B |
| D | C |
| A | E |
| E | Z |
+------+--------+
我想为每个朋友获取朋友的朋友。
为此我写了下面的查询
SELECT a.Name as Friend,b.Friend as FOF
FROM friends a
JOIN friends b
ON a.Friend = b.Name
通过该查询,我得到部分正确的输出如下
+--------+-----+
| Friend | FOF |
+--------+-----+
| A | C |
| D | C |
| A | Z |
+--------+-----+
在输出中我得到 C
作为 D
的 friend of friend
。(因为 D
是 B
和 C
的朋友是 B
) 的朋友,但 C
也是 D
的直接朋友。
所以我想更新查询以排除 friend of friend
这也是直接朋友
一个简单的方法是添加not exists
:
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE NOT EXISTS (SELECT 1
FROM friends f
WHERE f.Name = f1.Name and f.Friend = f2.Friend
);
如果 SQL 服务器支持元组,查询会怎样:
现场测试:http://sqlfiddle.com/#!17/14aec6/1
SELECT a.Name as Friend,b.Friend as FOF
FROM friends a
JOIN friends b ON a.Friend = b.Name
-- exclude fof if it is already in direct friends
WHERE (a.Name, b.Friend) NOT IN (select df.Name, df.Friend from friends df)
输出:
| friend | fof |
|--------|-----|
| A | C |
| A | Z |
您可以通过从派生 table 中删除别名来 simplify 查询,因为派生 table 通常不需要与外部查询相关联。即:
WHERE (a.Name, b.Friend) NOT IN (select Name, Friend from friends)
由于 SQL 服务器还不支持,您可以使用 EXISTS
/NOT EXISTS
代替。查看戈登的回答
你只需要过滤掉那些直接朋友的结果。
方法:1 使用 不存在
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE not exists (SELECT * FROM friends f WHERE f.Name = f1.Name and f.Friend = f2.Friend);
方法:2 使用 Not IN
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE (f1.name,f2.friend) not in (SELECT f3.name,f3.Friend from friends f3);
我有一个 friends
table 如下
+------+--------+
| Name | Friend |
+------+--------+
| A | B |
| B | C |
| D | B |
| D | C |
| A | E |
| E | Z |
+------+--------+
我想为每个朋友获取朋友的朋友。
为此我写了下面的查询
SELECT a.Name as Friend,b.Friend as FOF
FROM friends a
JOIN friends b
ON a.Friend = b.Name
通过该查询,我得到部分正确的输出如下
+--------+-----+
| Friend | FOF |
+--------+-----+
| A | C |
| D | C |
| A | Z |
+--------+-----+
在输出中我得到 C
作为 D
的 friend of friend
。(因为 D
是 B
和 C
的朋友是 B
) 的朋友,但 C
也是 D
的直接朋友。
所以我想更新查询以排除 friend of friend
这也是直接朋友
一个简单的方法是添加not exists
:
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE NOT EXISTS (SELECT 1
FROM friends f
WHERE f.Name = f1.Name and f.Friend = f2.Friend
);
如果 SQL 服务器支持元组,查询会怎样:
现场测试:http://sqlfiddle.com/#!17/14aec6/1
SELECT a.Name as Friend,b.Friend as FOF
FROM friends a
JOIN friends b ON a.Friend = b.Name
-- exclude fof if it is already in direct friends
WHERE (a.Name, b.Friend) NOT IN (select df.Name, df.Friend from friends df)
输出:
| friend | fof |
|--------|-----|
| A | C |
| A | Z |
您可以通过从派生 table 中删除别名来 simplify 查询,因为派生 table 通常不需要与外部查询相关联。即:
WHERE (a.Name, b.Friend) NOT IN (select Name, Friend from friends)
由于 SQL 服务器还不支持,您可以使用 EXISTS
/NOT EXISTS
代替。查看戈登的回答
你只需要过滤掉那些直接朋友的结果。
方法:1 使用 不存在
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE not exists (SELECT * FROM friends f WHERE f.Name = f1.Name and f.Friend = f2.Friend);
方法:2 使用 Not IN
SELECT f1.Name as Friend, f2.Friend as FOF
FROM friends f1 JOIN
friends f2
ON f1.Friend = f2.Name
WHERE (f1.name,f2.friend) not in (SELECT f3.name,f3.Friend from friends f3);