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

Вопрос, который вы задаете, представляется субъективным и, скорее всего, будет закрыт.

Я не удивился, увидев выше ужасное предупреждение, когда заполнял поле заголовка.

Я читаю почти каждую ветку, в которой говорится о друзьях друзейили общих друзьях, но я не уверен, что нашел правильное решение, которое хочу сделать.

Извините, я плохо разбираюсь в английском и SQL.

Как мне найти правильный ответ, если я плохо знаю оба языка?

Я решил, что должен спросить. Я не подведу себя из-за отрицательных голосовили любого предупреждения о дублировании.

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

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

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

Оба составных первичных ключатакже являются внешними ключами из таблицы PLAYER.

Я спросил и получил ответ от таких приятных людей, что «люди знают друг друга».

Представление SQL для ознакомления с таблицей.

И у меня такое мнение.

ACQUAINTANCE (VIEW)
-----------------------------------
PLAYER_ID(PK,FK)   FRIEND_ID(PK,FK)
-----------------------------------
1                  2                 // 1 knows 2
2                  1                 // 2 knows 1

Как вы могли заметить, бизнес-логика этих отношений преследует две цели.

  1. Один игрок может сказать, что знает кого-то еще.
  2. Когда оба человека говорят, что знают друг друга, их можно назвать знакомыми.

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

  1. Выбора других PLAYER_ID
  2. С заданным PLAYER(PLAYER_ID) (скажем, 1)
  3. Каждый из которых является одним из `друзей данного PLAYER's direct друзей
  4. Каждый из которых не является ИГРОКОМ (исключая 1 -> 2 -> 1)
  5. Каждый из которых не является прямым другом ИГРОКА (исключая 3 из 1 -> 2 -> 3 на 1 -> 3)
  6. Если возможно, отсортируйте по количеству общих друзей.

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

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

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

ОБНОВЛЕНИЕ -------------------------------------------------------------- ----------------

за комментарий Рафаэля Альтхауса чье имя совпадает с моей будущей дочерью(это имя мальчика?),

3 есть кандидат на друзей друзей 1потому что

1 knows 2
2 knows 3

но исключен потому что

1 already knows 3

В основном я хочу служить для данного игрока

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.

Спасибо ты.

ОБНОВЛЕНИЕ -------------------------------------------------------------- -----------------------

Я думаю, я должен шаг за шагом попробовать сам, исходя из того, что я узнал ОТ ЗДЕСЬ С РАЗЛИЧНЫМИ ЛЮДЬМИ даже если это неправильный ответ. Пожалуйста, дайте мне знать, если я делаю что-то не так.

Прежде всего, позвольте мне самому присоединиться к таблице 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

Поставление разныхобязательно сработает для основной цели

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 |
+-----------+-----+

Кто-нибудь может это подтвердить? Является ли этот запрос оптимальным? Любая возможная проблема с производительностью при создании представления?

Спасибо.

ОБНОВЛЕНИЕ -------------------------------------------------------------- ------------------------------------------------------------

I создал представление как

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)

16
задан Community 23 May 2017 в 12:13
поделиться