Sozialnetzwerk / schwerer Join

raven

Well-known member
20 April 2006
5.038
540
Hallo,

ich brauch mal eure Hilfe ;)
Ich habe eine Datenbank-Tabelle welche Freundschaften speichert:
ct_social_friend
- userID: int(10) unsigned
- friendID: int(10) unsigned

Eine Freundschaft gilt nur als geschlossen, wenn es zwei Records pro Freundschaft gibt, also wenn 1 und 2 befreundet sind gibt es einmal den Record 1 => 2 und einmal 2 => 1

Das ist mein kleines Sozialnetzwerk, was ich zum Test in die Datenbank eingespielt habe; wichtig für das Problem gleich ;) : https://www.7pics.info/?image=socialtest_697.gif
Die gegenseitigen Pfeile stehen für geschlossene Freundschaften, die (durchgestrichenen) Pfeile mit nur einem "Kopf" stehen für Anträge auf Freundschaften, welche noch nicht angenommen oder abgelehnt wurden.

Ich möchte nun sämtliche Freundesfreunde herausfinden. Bisher hab ichs so versucht, aber da kommt weitestgehend nur Müll raus:
PHP:
SELECT a.userID, c.friendID FROM ct_social_friend a INNER JOIN ct_social_friend c ON c.userID = a.friendID AND c.friendID != a.userID
Das Ergebnis ist folgendes: https://www.7pics.info/?image=erg_015.jpg

Zu bemängeln ist da:
:arrow: 1 und 3 sind Freunde. Es wird trotzdem ein DB-Record als "Freundesfreund" angezeigt, ich leite das darauf zurück, dass er 3 als Freundesfreund von 5 erkennt (5 ist kein Freund; mehr dazu gleich - sobald 5 echter Freund ist, darf 3 trotzdem nicht als Freundesfreund von 1 eingeblendet werden)
:arrow: 1 hat nur Antrag auf Freundschaft bei 5 gestellt, 5 hat noch nicht reagiert (= es gibt einen DB-Record, nicht zwei: 1 => 5), 2 erkennt 5 trotzdem als Freundesfreund - die Abfrage ist noch nicht implementiert, weil mir keine Lösung einfällt.
:arrow: 3 und 5 sind Freunde, werden ebenfalls als Freundesfreunde dargestellt. Ich führe das auf das gleiche Dreiecksproblem wie ganz oben zurück.
:arrow: 6 hat nur Antrag auf Freundschaft bei 1 gestellt, sieht 3 und 2 aber trotzdem als Freundesfreunde, sowie 5, der ebenfalls noch nicht bestätigt ist. Das führe ich wiederum auf das Problem 2 zurück, weil mir keine gescheite Abfrage einfällt, um das zu verhindern.

Ich könnte das ganze zwar lösen, indem ich die Daten in PHP verarbeite, möchte das aber gerne direkt in der Datenbank lösen (allein aus Performancegründen) .
Vielleicht hat ja jemand eine Idee und Lust, mir ein wenig weiterzuhelfen ;)

Danke,
raven

P.S.: Nach Möglichkeit würde ich dieses Prinzip gerne auf weitere Freundschaftsstufen übernehmen, ein bisschen Flexibilität im Query wäre also schön ;)
 
Spontan würd ich jetz zu einem not in tendieren aber das muss ja dann auch meitens irgendwie in einem join machbar sein.

Hmm ist für mich zu hoch hoff dir kann jmd anders helfen ;)

mfg
Samy
 
Zuletzt bearbeitet:
Spontan würd ich es so versuchen das ich die Tabelle 2 mal mit sich selbst Joine. Weiß jetzt nicht ob es hinhaut oder ob ich nen Denkfehler hab (was mich nach gestern nicht verwundern würde :ugly:), hab aber auch keine lust zu testen.

Jedenfalls sowas in der Art schwebt mir grade im Kopf rum:

PHP:
SELECT
   t1.user_id,
   t1.friend_id
FROM
   table AS t1 INNER JOIN
   table AS t2 ON (t1.firend_id = t2.user_id) INNER JOIN
   table AS t3 ON (t2.firend_id = t3.user_id AND t3.user_id = t1.user_id)

*edit* Ich glaub die 3te Tabelle ist überflüssig. Es reicht auch nur einem Join und "t1.firend_id = t2.user_id AND t2.firend_id = t1.user_id"
 
Ich frag mich, warum du das so umständlich löst. Du erweiterst die ct_social_friend Tabelle um ein weiteres Attribut, das angibt, welchen Status die Freundschaft hat. z.B. 0: wartend , 1: akzeptiert.
Dazu nimmst du die Regel, dass der, der ein Freundschaftsangebot macht, immer die erste Spalte belegt, der der das Angebot bekommt die zweite. Nur damit du weißt, wer welchen Status angezeigt bekommt (bei 0: warte auf Bestätigung / Freundschaft annehmen oder ablehnen ; bei 1: keine Unterscheidung mehr)

Dann sind auch Freundesfreunde, Trustchains etc. kein Problem mehr.