Вот как выполнить поиск, используя поиск по кратчайшему пути в ширину, используя JOIN.В этом алгоритме нет ничего волшебного, так как мы используем MySQL, чтобы найти наш ответ, и мы не включаем какой-либо причудливый алгоритм поиска, который использует какие-либо эвристические методы или оптимизацию.
Моя таблица «друзей»однонаправленные отношения, поэтому у нас есть дубликаты в том смысле, что хранятся как «от 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 участник, и мы просим 1 друзей с 7, aдруг друга и т.д?Число 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