Gemeinsame Freunde

  • Hi,


    ich brauche mal wirklich Hilfe mit meinem SQL Statement. Ich wollte User anzeigen, wo z.b steht der User hat von meiner Freundesliste 3 gemeinsame Freunde.


    Kennt ihr bestimmt aus Facebook/Instagram, dass da steht:


    Max Mustermann


    3 gemeinsame Freunde


    Wie finde ich die 3 gemeinsame freunde in einem SQL Statement heraus bzw wie sollte der SQL Code aussehen? Hab ganze zeit ausprobiert bekomme das aber nicht hin, hab eine richtige Blockade vor meinem Kopf. Komme einfach nicht weiter.


    Hab halt 2 Tabellen.


    1. User


    2. Follow


    Das wäre z.b um alle meine Follower anzeigen zu lassen.


    Aber müsste man nicht um gemeinsame Freunde anzeigen zu lassen iwie prüfen wo meine Freunde == seine freunde Abboniert hat oder so? Das macht mir richtig kopfschmerzen komme gar nicht mehr mit. Weiß eventuell einer einen Weg?

  • Deine Datenbank muss erweitert werden, im einfachsten Fall um eine Tabelle, bspw.: FriendshipMappings


    id (int, auto_increment, primary_key) | userid (int) | userfriendid (int) | friendship_since (datetime)


    Wenn jetzt User 1 mit User 5 befreundet ist sieht der Datensatz halt in etwa so aus:


    1 | 1| 5| 2018-05-21 13:24


    Das Mapping gilt in beide Richtungen, also wenn User 1 mit User 5 befreundet ist, ist User 5 natürlich auch mit User 1 befreundet.

    Ich würde den User, der die Freundschaftsanfrage gestellt ha immer zuerst nennen, dann hast Du auch eine Auswertungsbasis darüber, wer die Freundschaft initiiert hat, ohne dafür extra noch Tabellen führen zu müssen.


    Das ist aber nur ein grundsäzlicher, einfacher Ansatz. Es gibt dazu natürlich auch weitaus komplexere Lösungen, die Dir hier aber glaube ich nicht weiter helfen würden.

  • Stimmt. Hatte letztens überlegt das über die follower zu lösen.

    Das macht ja aber keinen Sinn.

    Jeder kann jemanden folgen (der gefolgte kann sich nicht wehren).

    Aber eine Freundschaft muss bestätigt werden.

    Also neue Tabelle.


    Arnes Ansatz ist schön einfach.

    Das einzigste, was mir noch einfällt wäre,

    dass Du zwei Tabellen nutzt:

    friend_request

    friend


    In friend_request speicherst Du Anfragen.

    Ein Feld created_at gibt an, wann die Anfrage erstellt wurde.

    Nach n Tagen läuft die request dann aus und der Eintrag wird gelöscht.

    (Du brauchst dort eigtl kein Auto increment).

    Wird die request angenommen, wird der Eintrag auch gelöscht.

    Dann aber bekommt die Tabelle friends den gemeinsamen Eintrag.


    Evtl reicht jetzt auch eine Zeile in friends:

    user ID |user id | created_at


    (Kann das nicht zu Ende denken. Bin mehr damit beschäftigt mit dem Tablet zu schreiben ;D

    )

  • Danke erstmal für die Info :)


    Nur kleine Frage:

    Wie soll das denn gehen das, wenn User 1 den User 5 folgt, dass gleichzeitig User 5 den User 1 folgt (bzw befreundet sind).


    Bei mir ist es ja so: User 1 folgt User 5.


    Dies wird so in die Datenbank eingetragen:


    id | user_id | follow_id | date

    1 | 1 | 5 | ...


    (user_id) ist der Inviter bzw der den "Button" folgen jetzt geklickt hat und den jenigen Folgen möchte, und Follow_id ist da welche Person er folgt (sozusagen der Accepter).


    Wenn User 5 jetzt User 1 folgt, dann sieht das halt andersrum aus.


    id | user_id | follow_id | date

    1 | 5 | 1 | ...


    Deswegen verstehe ich nicht wieso jetzt wenn User 1 den User 5 folgt, dass User 5 automatisch mit User1 befreundet ist. bzw den auch sozusagen folgt.



    Hi danke auch für die Info,


    wozu aber eine zweite Tabelle?


    Ich hab doch bereits eine.


    meine Tabelle sieht so aus , hab vergessen die Spalte "Process" mitzuschreiben.


    id | user_id | follow_id | process | date


    Process ist immer auf 1, sollte der User Privat sein ist process auf 0 und wird erst auf 1 gestellt, wenn der User es angenommen hat.

  • Du hängst Dich zu sehr an "follow" auf.


    Was Du bauen musst|willst|solltest, ist ein komplett neues|eigenständige Feature - "friend".


    Folgen kann jeder. Auch wenn einer evtl nicht will, dass jemand ihm folgt.

    Aber Befreundet sein - das muss von beiden Seiten akzeptiert werden (einer lädt ein, der Andere stimmt zu).


    DRAFT:

    Die Tabellen brauchen wohl keine id (auto increment id).

    Denn wenn Du die Request (tbl friend_request) löschst (abgelaufen|verweigert), oder die Freundschaft aufgelöst wird (tbl friend),

    dann würde das Lücken hinterlassen (ids verbrannt).


    INDEX:

    tbl friend_request index auf user_id_from, user_id_to, created_at

    tbl friend index auf user_id_from, user_id_to


    DEFAULT VALUE:

    tbl friend_request und friend column created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP


    (Sorry, bissl unübersichtlich, aber muss schlafen gehen :D)



    EDIT:

    Wenn beide - zB user 1 und 5 - sich gegenseitig eine Freundschaftsanfrage zusenden,

    dann kann es gleich als akzeptiert angesehen werden.

    Bsp:

    2018-05-22 00:00:10 user 1 erstellt friends request auf user 5.

    Suche in tbl friend_request, ob user 1 schon eine request auf diesen user erstellt hat.

    Ja? Dann gleich in tbl friend eintragen.

    Sonst: Eintrag in tbl friend_request.


    (5 min später)

    2018-05-22 00:05:10 user 5 erstellt friends request auf user 1.

    Suche in tbl friend_request, ob user 1 schon eine request auf diesen user erstellt hat.

    Ja? Dann gleich in tbl friend eintragen.

    Sonst: Eintrag in tbl friend_request.


    Hoffe es ist irgendwie verständlich :)

  • Zwei weitere Tabellen sind bspw. in Bezug auf Normalisierung klar die sinnvollere Variante.

    Dennoch würde ich das in diesem Fall tatsächlich mit einer einzigen Freundestabelle lösen:


    id (int,auto_increment,primary_key) | userid (int,index) | friendid (int,index) | requested (datetime) | confirmed (datetime)


    Wenn man sich nun an die Voraussetzung hält, dass der Benutzer in der Spalte UserId die Freundschaftsanfrage initiiert hat, ist damit alles abgedeckt.

    An der Spalte requested kann ausgelesen werden wann der Benutzer ( userid ) einen Anfrage an wen ( friendid) gestellt hat.

    Die Spalte confirmed gibt an, wann der angefragte (friendid) diese akzeptiert hat. Solange confirmed NULL ist, ist es eine unbestätigte Anfrage!


    Die Freundschaft selber liest sich natürlich bidirektional, d.h. für jeden User muss auf userid und friendid gemapped werden.