SQL выбирает людей, которых вы знаете

The question you're asking appears subjective and is likely to be closed.

Я не был удивлен, когда увидел вышеhorrible warning пока я заполнял поле заголовка.

Я читаю почти все темы, говорящие оfriends of friends или жеmutual friends но я не уверен, что нашел правильное решение, которое хочу сделать.

Мне жаль, что я не очень хорош ни в английском, ни в SQL.

Как я могу найти правильный ответ, будучи не очень хорошим на обоих языках?

Я решил, что должен спросить. Я не позволю себеdown-voteс или любойduplication warnings.

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

У меня есть таблица для дружеских отношений.

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

Как вы могли заметить, эти отношения & apos; Бизнес-логика преследует две цели.

One player can say he or she knows someone else. When both people say they know each other, they can be said as acquaintance.

И теперь я хочу знать, есть ли хороший способ для

Selecting other PLAYER_IDs With given PLAYER(PLAYER_ID) (say 1) Which each is one of `friends of given PLAYER's direct friends' Which each is not the PLAYER himself (excluding 1 -> 2 -> 1) Which each is not the PLAYER's direct friends (excluding 3 from 1 -> 2 -> 3 by 1 -> 3) Order by number of mutual friends if possible.

Я думаю, что ответ Джастина Нисснера в& quot; люди, которых вы можете знать & quot; SQL-запрос это ближайший путь, по которому я должен идти.

Заранее спасибо.

Я закрою ветку, если эта тема действительно дублирована и не нужна.

ОБНОВИТЬ ------------------------------------------------- -------------

для комментария Рафы Альтауса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 |
+-----------+

не являются прямыми известными

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)
 O. Jones11 июн. 2012 г., 15:05
Что бы это ни стоило, вы применяете раздел математики, известный как теория графов. Если вы будете заниматься чем-то большим, чем тривиальный объем работы по этой проблеме, вам было бы целесообразно прочитать книгу об этом. В нем много тонкостей. За советом о том, как выучить этот материал, попробуйте programmers.stackexchange.com
 Neville Kuyt11 июн. 2012 г., 14:54
Вы ожидаете, что полученный SQL вернет 4?
 Raphaël Althaus11 июн. 2012 г., 14:35
точка 1 = & gt; 3 не так ясно в моих (бедных) глазах. Не могли бы вы дать набор данных и точный результат, который вы хотели бы получить, возможно (или просто результат, который вы хотели бы получить, если ваш набор данных достаточен).

Ответы на вопрос(1)

Решение Вопроса

EDIT

SELECT `friend_id` AS `possible_friend_id`
FROM `friends`
WHERE `player_id` IN (        --selecting those who are known
    SELECT `friend_id`        --by freinds of #1
    FROM `friends`
    WHERE `player_id` = 1) 
AND `friend_id` NOT IN (      --but not those who are known by #1
    SELECT `friend_id`
    FROM `friends`
    WHERE `player_id` = 1)
AND NOT `friend_id` = 1       --and are not #1 himself
                              --if one is known by multiple people
                              --he'll be multiple time in the list
GROUP BY `possible_friend_id` --so we group
ORDER BY COUNT(*) DESC        --and order by amount of repeatings
 12 июн. 2012 г., 08:53
проверьте обновленный ответ
 Jin Kwon12 июн. 2012 г., 03:36
Я удивлен, что ваш запрос показывает те же результаты, что и мой с join. Спасибо. Можете ли вы занять несколько минут для заказа по количеству общих друзей?
 11 июн. 2012 г., 19:22
это, я выбираю всех друзей всех игроков, которые являются друзьями 1
 13 июн. 2012 г., 15:23
@JinKwon ты назовешь хотя бы кошку или что-то после меня?
 Jin Kwon11 июн. 2012 г., 16:49
Спасибо за ваш ответ, сэр. Я понимаю 2 и 3 условия. Но я едва могу понять 1-е условие. Это действительно запрос для поискаfriends of friends?

Ваш ответ на вопрос