自我加入在SQL中获取朋友的朋友

问题描述 投票:0回答:3

我有一张friends表如下

+------+--------+
| 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作为friend of friendD。(因为DB的朋友,CB的朋友)但是C也是D的直接朋友。

所以我想更新查询以排除friend of friend,这也是直接的朋友

sql sql-server self-join
3个回答
2
投票

一个简单的方法是添加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
                 );

1
投票

你只需要过滤掉那些直接朋友的结果。

方法:1使用Not Exist

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);

1
投票

如果SQL Server具有元组支持,查询将如何:

现场测试: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 |

您可以通过从派生表中删除别名来simplify查询,因为派生表通常不需要与外部查询相关联。以机智:

WHERE (a.Name, b.Friend) NOT IN (select Name, Friend from friends)

由于SQL Server尚不支持,您可以使用EXISTS / NOT EXISTS。见戈登的回答

© www.soinside.com 2019 - 2024. All rights reserved.