SQL选择您可能认识的人

Jin*_*won 16 mysql sql

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

当我在填充标题字段时看到上面可怕的警告时,我并不感到惊讶.

我几乎每个线程都在阅读friends of friends,mutual friends但我不确定我找到了正确的解决方案.

对不起,我不擅长英语,也不擅长SQL.

如何在不擅长这两种语言的同时找到正确的答案?

我决定要问.我不会因为down-votes或任何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
Run Code Online (Sandbox Code Playgroud)

两者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
Run Code Online (Sandbox Code Playgroud)

您可能会注意到,这种关系的业务逻辑有以下两个目的.

  1. 一个玩家可以说他或她认识别人.
  2. 当两个人都说他们彼此认识时,他们可以说是熟人.

而且,现在,我想知道有什么好办法

  1. 选择其他PLAYER_ID
  2. 给定的PLAYER(PLAYER_ID)(比如1)
  3. 每个人都是'给予PLAYER的直接朋友'的朋友之一
  4. 哪个不是PLAYER自己(不包括1 - > 2 - > 1)
  5. 哪个不是PLAYER的直接朋友(不包括3个从1 - > 2 - > 3乘1 - > 3)
  6. 如果可能,按共同朋友的数量排序.

我认为Justin Niessner在"你可能知道的人"sql查询中的答案是我必须遵循的最接近的路径.

提前致谢.

如果这个主题真的重复而且没有必要,我将关闭该主题.

更新------------------------------------------------- -------------

对于RaphaëlAlthaus的评论whose name is same with my future daughter(这是男孩的名字吗?),

3是friends of friends of 1因为的候选人

1 knows 2
2 knows 3
Run Code Online (Sandbox Code Playgroud)

但排除因为

1 already knows 3
Run Code Online (Sandbox Code Playgroud)

基本上,我想以服务为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
Run Code Online (Sandbox Code Playgroud)

有了上表

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.
Run Code Online (Sandbox Code Playgroud)

谢谢.

更新------------------------------------------------- --------------------

我想我必须从我所学到的东西中一步一步地尝试,FROM HERE WITH VARIOUS PEOPLE即使这不是正确的答案.如果我做错了,请告诉我.

首先,让我自己加入FRIEND表.

SELECT *
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+-----------+-----------+-----------+
| 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 |
+-----------+-----------+-----------+-----------+
Run Code Online (Sandbox Code Playgroud)

仅限F2.FRIEND_ID

SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+
| FRIEND_ID |
+-----------+
|         1 |
|         3 |
|         4 |
|         5 |
|         5 |
|         2 |
|         3 |
|         5 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

仅限1

SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1;
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+
| FRIEND_ID |
+-----------+
|         1 |
|         3 |
|         4 |
|         5 |
|         5 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

不是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;
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+
| FRIEND_ID |
+-----------+
|         3 |
|         4 |
|         5 |
|         5 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

不是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);
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|         5 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

我想我到了那里.

更新------------------------------------------------- ----------------

添加了以下路径

1 -> 100 -> 400
1 -> 200 -> 400
1 -> 300 -> 400
Run Code Online (Sandbox Code Playgroud)

最后一个查询打印(再次)

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|         5 |
|       400 |
|       400 |
|       400 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

最后,我得到了候选人: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);
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|       400 |
+-----------+
Run Code Online (Sandbox Code Playgroud)

而且,现在,需要按相互排序进行排序.

每个候选人都有共同朋友的数量.

+-----------+
| 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)
+-----------+
Run Code Online (Sandbox Code Playgroud)

如何通过这些共同的朋友来计算和排序?

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;
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+----------+
| FRIEND_ID | COUNT(*) |
+-----------+----------+
|         4 |        1 |
|         5 |        2 |
|       400 |        3 |
+-----------+----------+
Run Code Online (Sandbox Code Playgroud)

我知道了!

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;
Run Code Online (Sandbox Code Playgroud)

版画

+-----------+-----+
| FRIEND_ID | MFC |
+-----------+-----+
|       400 |   3 |
|         5 |   2 |
|         4 |   1 |
+-----------+-----+
Run Code Online (Sandbox Code Playgroud)

任何人都可以确认一下吗?该查询是否最佳?将其作为视图时出现任何可能的性能问题?

谢谢.

更新------------------------------------------------- -------------------------------------------

我创建了一个视图

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;
Run Code Online (Sandbox Code Playgroud)

并测试过.

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)
Run Code Online (Sandbox Code Playgroud)

Val*_*rij 7

使用此 编辑

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
Run Code Online (Sandbox Code Playgroud)

  • @JinKwon你会给我起一个至少一只猫的名字吗? (3认同)