Самостоятельно присоединиться, чтобы завести друзей в SQL - PullRequest
0 голосов
/ 19 апреля 2019

У меня есть таблица 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 friend из D. (Потому чтоD является другом B, а C является другом B), но C также является прямым другом D.

Поэтому я хочу обновить запрос, чтобы исключить friend of friend которые также являются прямыми друзьями

Ответы [ 3 ]

2 голосов
/ 19 апреля 2019

Простой метод - добавить 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 голос
/ 19 апреля 2019

Вам просто нужно отфильтровать результаты, которые также являются прямыми друзьями.

Метод: 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);
1 голос
/ 19 апреля 2019

Как бы хотелось запросу, если 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 |

Вы можете упрощает запрос, удаляя псевдоним из производной таблицы, поскольку производная таблица обычно не должна коррелировать с внешним запросом.То есть:

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

Поскольку SQL Server пока не поддерживает это, вы можете использовать EXISTS / NOT EXISTS.Смотри ответ Гордона

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...