The question you're asking appears subjective and is likely to be closed.
Я не удивился, увидев выше ужасное предупреждение, когда я заполнял поле заголовка.
Я читаю почти каждый поток, говорящий о friends of friends
или mutual friends
, но я не уверен, что нашел правильное решение, которое я хочу сделать.
Мне жаль, что я плохо разбираюсь в английском и SQL.
Как я могу найти правильный ответ, не будучи хорошим на обоих языках?
Я решил, что должен спросить. Я не позволю себе отказаться от down-vote
или любых duplication warning
s.
Как я хочу получить ответ, я напишу как можно более искренне, чтобы можно было помочь любым другим подобным проблемам.
У меня есть таблица для отношений друзей.
FRIEND (TABLE)
-----------------------------------
PLAYER_ID(PK,FK) FRIEND_ID(PK,FK)
-----------------------------------
1 2 // 1 knows 2
2 1 // 2 knows 1
1 3 // 1 knows 3
2 3 // 2 knows 3
2 4 // 2 knows 4
2 5 // 2 knows 5 // updated
3 5 // 3 knows 5 // updated
1 100
1 200
1 300
100 400
200 400
300 400
Оба composite primary keys
также являются внешними ключами из таблицы PLAYER
.
Я спросил и получил ответы от таких хороших людей, что "люди знают друг друга".
SQL-представление для ознакомления из таблицы.
И у меня такое мнение.
ACQUAINTANCE (VIEW)
-----------------------------------
PLAYER_ID(PK,FK) FRIEND_ID(PK,FK)
-----------------------------------
1 2 // 1 knows 2
2 1 // 2 knows 1
Как вы могли заметить, бизнес-логика этих отношений имеет следующие две цели.
- Один игрок может сказать, что он или она знает кого-то еще.
- Когда оба говорят, что знают друг друга, их можно назвать знакомством.
И теперь я хочу знать, есть ли хороший способ для
- Выбор других PLAYER_IDs
- С данным PLAYER (PLAYER_ID) (скажем 1)
- Каждый из них является одним из "друзей заданных прямых друзей".
- Каждый из них не сам ИГРОК (исключая 1 → 2 → 1)
- Каждый из них не является прямым друзьями PLAYER (исключая 3 из 1 → 2 → 3 на 1 → 3)
- Заказ по количеству общих друзей, если это возможно.
Я думаю, что Джастин Нисснер ответил в "людям, которых вы, возможно, знаете" sql query является ближайшим путем, которым я должен следовать.
Спасибо заранее.
Я закрою поток, если этот предмет действительно дублируется и не нужен.
ОБНОВЛЕНИЕ ---------------------------------------------- ----------------
для комментария Raphaël Althaus whose name is same with my future daughter
(это имя мальчика?),
3 является кандидатом на friends of friends of 1
, потому что
1 knows 2
2 knows 3
но исключено, потому что
1 already knows 3
В основном я хочу служить для given player
people he or she may know
which is not himself or herself // this is nothing but obvious
which each is not already known to himself
С приведенной выше таблицей
by 1 -> 2 -> 4 and 1 -> 3 -> 5
4 and 5 can be suggested for 1 as 'people you may know'
order by number of mutual friends will be perfect
but I don't think I can understand even if someone show me how. sorry.
Спасибо.
ОБНОВЛЕНИЕ ---------------------------------------------- -----------------------
Я думаю, что я должен попробовать шаг за шагом сам из того, что я узнал FROM HERE WITH VARIOUS PEOPLE
, даже если это не правильный ответ.
Пожалуйста, дайте мне знать, если я что-то сделаю неправильно.
Прежде всего, позвольте мне самостоятельно присоединиться к самой таблице FRIEND.
SELECT *
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
печатает
+-----------+-----------+-----------+-----------+
| PLAYER_ID | FRIEND_ID | PLAYER_ID | FRIEND_ID |
+-----------+-----------+-----------+-----------+
| 1 | 2 | 2 | 1 |
| 1 | 2 | 2 | 3 |
| 1 | 2 | 2 | 4 |
| 1 | 2 | 2 | 5 |
| 1 | 3 | 3 | 5 |
| 2 | 1 | 1 | 2 |
| 2 | 1 | 1 | 3 |
| 2 | 3 | 3 | 5 |
+-----------+-----------+-----------+-----------+
Только F2.FRIEND_ID
SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
печатает
+-----------+
| FRIEND_ID |
+-----------+
| 1 |
| 3 |
| 4 |
| 5 |
| 5 |
| 2 |
| 3 |
| 5 |
+-----------+
только для 1
SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1;
печатает
+-----------+
| FRIEND_ID |
+-----------+
| 1 |
| 3 |
| 4 |
| 5 |
| 5 |
+-----------+
не 1
SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1
AND F2.FRIEND_ID != 1;
печатает
+-----------+
| FRIEND_ID |
+-----------+
| 3 |
| 4 |
| 5 |
| 5 |
+-----------+
не известно 1
SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1
AND F2.FRIEND_ID != 1
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1);
печатает
+-----------+
| FRIEND_ID |
+-----------+
| 4 |
| 5 |
| 5 |
+-----------+
Думаю, я добираюсь туда.
ОБНОВЛЕНИЕ ---------------------------------------------- -------------------
Следующие добавленные пути
1 -> 100 -> 400
1 -> 200 -> 400
1 -> 300 -> 400
И последний запрос печатает (снова)
+-----------+
| FRIEND_ID |
+-----------+
| 4 |
| 5 |
| 5 |
| 400 |
| 400 |
| 400 |
+-----------+
наконец, я получил кандидатов: 4, 5, 400
Полагая distinct
, безусловно, работаем для основной цели
SELECT DISTINCT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1
AND F2.FRIEND_ID != 1
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1);
печатает
+-----------+
| FRIEND_ID |
+-----------+
| 4 |
| 5 |
| 400 |
+-----------+
И теперь нужно упорядочить по взаимным подсчетам.
Здесь приходит количество общих друзей для каждого кандидата.
+-----------+
| FRIEND_ID |
+-----------+
| 4 | 1 (1 -> 2 -> 4)
| 5 | 2 (1 -> 2 -> 5, 1 -> 3 -> 5)
| 400 | 3 (1 -> 100 -> 400, 1 -> 200 -> 400, 1 -> 300 -> 400)
+-----------+
Как я могу рассчитать и заказать по количеству друзей?
SELECT F2.FRIEND_ID, COUNT(*)
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1
AND F2.FRIEND_ID != 1
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1)
GROUP BY F2.FRIEND_ID;
печатает
+-----------+----------+
| FRIEND_ID | COUNT(*) |
+-----------+----------+
| 4 | 1 |
| 5 | 2 |
| 400 | 3 |
+-----------+----------+
Я понял!
SELECT F2.FRIEND_ID, COUNT(*) AS MFC
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1
AND F2.FRIEND_ID != 1
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1)
GROUP BY F2.FRIEND_ID
ORDER BY MFC DESC;
печатает
+-----------+-----+
| FRIEND_ID | MFC |
+-----------+-----+
| 400 | 3 |
| 5 | 2 |
| 4 | 1 |
+-----------+-----+
Может ли кто-нибудь подтвердить это? Оптимален ли этот запрос? Любая возможная проблема с производительностью при создании ее как вида?
Спасибо.
ОБНОВЛЕНИЕ ---------------------------------------------- ----------------------------------------------
Я создал представление как
CREATE VIEW FOLLOWABLE AS
SELECT F1.PlAYER_ID, F2.FRIEND_ID AS FOLLOWABLE_ID, COUNT(*) AS MFC
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F2.FRIEND_ID != F1.PLAYER_ID
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = F1.PLAYER_ID)
GROUP BY F2.FRIEND_ID
ORDER BY MFC DESC;
и протестирован.
mysql> select * from FOLLOWABLE;
+-----------+---------------+-----+
| PlAYER_ID | FOLLOWABLE_ID | MFC |
+-----------+---------------+-----+
| 1 | 400 | 3 |
| 1 | 5 | 2 |
| 2 | 100 | 1 |
| 2 | 200 | 1 |
| 2 | 300 | 1 |
| 1 | 4 | 1 |
+-----------+---------------+-----+
6 rows in set (0.01 sec)
mysql> select * from FOLLOWABLE WHERE PLAYER_ID = 1;
+-----------+---------------+-----+
| PlAYER_ID | FOLLOWABLE_ID | MFC |
+-----------+---------------+-----+
| 1 | 400 | 3 |
| 1 | 5 | 2 |
| 1 | 4 | 1 |
+-----------+---------------+-----+
3 rows in set (0.00 sec)