SQL wybierający osoby, które możesz znać

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

Nie byłem zaskoczony, kiedy zobaczyłem powyżejstraszne ostrzeżenie podczas wypełniania pola tytułu.

Czytam prawie każdy wątek, o którym mówięfriends of friends lubmutual friends ale nie jestem pewien, czy znalazłem właściwe rozwiązanie, które chcę zrobić.

Przepraszam, że nie jestem dobry w języku angielskim ani SQL.

Jak mogę znaleźć właściwą odpowiedź, nie będąc dobrym w obu językach?

Zdecydowałem, że muszę zapytać. Nie zawiodę się zadown-votes lub jakikolwiekduplication warnings.

Ponieważ chcę odpowiedzi, spiszę tak szczerze, jak to tylko możliwe, na wszelkie dalsze podobne problemy.

Mam stół do kontaktów z przyjaciółmi.

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

Obiecomposite primary keys są również kluczami zagranicznymiPLAYER stół.

Zapytałem i dostałem odpowiedź od takich miłych ludzi za „ludzie się znają”.

Widok SQL dla znajomego z tabeli.

I mam taki widok.

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

Jak można zauważyć, logika biznesowa tych relacji ma dwa następujące cele.

Jeden gracz może powiedzieć, że zna kogoś innego.Kiedy obaj mówią, że się znają, można powiedzieć, że są znajomymi.

A teraz chcę wiedzieć, czy jest na to jakiś dobry sposób

Wybór innych PLAYER_IDsZ podanym PLAYEREM (PLAYER_ID) (powiedzmy 1)Który z nich jest jednym z „przyjaciół bezpośrednich przyjaciół PLAYERA”Który z nich nie jest samym GRACZEM (z wyjątkiem 1 -> 2 -> 1)Które z nich nie są bezpośrednimi przyjaciółmi GRACZA (z wyjątkiem 3 z 1 -> 2 -> 3 o 1 -> 3)Jeśli to możliwe, zamawiaj według liczby wspólnych znajomych.

Myślę, że odpowiedź Justina Niessnera wKwerenda sql „ludzie, których możesz znać” jest najbliższą ścieżką, którą muszę podążać.

Z góry dziękuję.

Zamknę wątek, jeśli temat jest naprawdę powielony i nie jest potrzebny.

AKTUALIZACJA ------------------------------------------------- -------------

dla komentarza Raphaël Althauswhose name is same with my future daughter (czy to imię chłopca?),

3 jest kandydatem dofriends of friends of 1 bo

1 knows 2
2 knows 3

ale wykluczone, ponieważ

1 already knows 3

Zasadniczo chcę służyć zagiven 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

Z powyższym stołem

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.

Dziękuję Ci.

AKTUALIZACJA ------------------------------------------------- --------------------

Myślę, że muszę próbować krok po kroku sam z tego, czego się nauczyłemFROM HERE WITH VARIOUS PEOPLE nawet jeśli nie jest to właściwa odpowiedź. Daj mi znać, jeśli zrobię coś złego.

Przede wszystkim pozwól mi dołączyć do samego stołu PRZYJACIELA.

SELECT *
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID

wydruki

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

Tylko F2.FRIEND_ID

SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID

wydruki

+-----------+
| FRIEND_ID |
+-----------+
|         1 |
|         3 |
|         4 |
|         5 |
|         5 |
|         2 |
|         3 |
|         5 |
+-----------+

tylko dla 1

SELECT F2.FRIEND_ID
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID
WHERE F1.PLAYER_ID = 1;

wydruki

+-----------+
| FRIEND_ID |
+-----------+
|         1 |
|         3 |
|         4 |
|         5 |
|         5 |
+-----------+

nie 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;

wydruki

+-----------+
| FRIEND_ID |
+-----------+
|         3 |
|         4 |
|         5 |
|         5 |
+-----------+

nie znane są bezpośrednie 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);

wydruki

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|         5 |
+-----------+

Myślę, że tam dotrę.

AKTUALIZACJA ------------------------------------------------- ----------------

Dodano następujące ścieżki

1 -> 100 -> 400
1 -> 200 -> 400
1 -> 300 -> 400

A ostatnie zapytanie zostanie wydrukowane (ponownie)

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|         5 |
|       400 |
|       400 |
|       400 |
+-----------+

w końcu dostałem kandydatów: 4, 5, 400

Puttingdistinct na pewno działa dla głównego celu

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);

wydruki

+-----------+
| FRIEND_ID |
+-----------+
|         4 |
|         5 |
|       400 |
+-----------+

A teraz potrzebne jest zamówienie przez wzajemne liczenie.

Nadchodzi liczba wzajemnych przyjaciół dla każdego kandydata.

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

Jak mogę obliczyć i zamówić według liczby znajomych?

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;

wydruki

+-----------+----------+
| FRIEND_ID | COUNT(*) |
+-----------+----------+
|         4 |        1 |
|         5 |        2 |
|       400 |        3 |
+-----------+----------+

Mam to!

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;

wydruki

+-----------+-----+
| FRIEND_ID | MFC |
+-----------+-----+
|       400 |   3 |
|         5 |   2 |
|         4 |   1 |
+-----------+-----+

Czy ktoś może to potwierdzić? Czy to zapytanie jest optymalne? Jakikolwiek możliwy problem z wydajnością, gdy jest to widok?

Dziękuję Ci.

AKTUALIZACJA ------------------------------------------------- -------------------------------------------

Stworzyłem widok jako

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;

i przetestowany.

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)

questionAnswers(1)

yourAnswerToTheQuestion