2016-11-15 8 views
4

Also ich glaube, ich brauche einen Inner Join für diese Abfrage, aber bin mir nicht 100% sicher.SQL Inner Join mit 3 Tabellen

Zu allererst sehen meine Datenbank-Diagramm:

Click here for database diagram

Was ich versuche zu erreichen:

  • Ich versuche, alle Nachrichten zu erhalten (so user_username , text, posted_at FROM-Nachrichten), wobei der user_username mit dem folged_username übereinstimmt und wo der folged_username einen follower_username hat, der =?
  • Also im Wesentlichen alle gefolgt von?, Ich möchte alle ihre Nachrichten erhalten.

Wo? = Ein inputed Benutzername

Was ich bisher versucht habe

ich eine Reihe von SQL-Anweisungen versucht haben und haben bisher nicht gelungen, erfolgreich zu bekommen sein. Dies sind einige, die ich versucht habe.

$sql = "SELECT user_username, text, posted_at FROM Messages, Users, User_Follows WHERE user_username = (SELECT username FROM Users WHERE username = (SELECT followed_username FROM User_Follows WHERE follower_username = ?)) ORDER BY posted_at DESC;"; 
$sql = "SELECT user_username, text, posted_at FROM Messages, User_Follows WHERE follower_username = ? AND followed_username = user_username;"; 
$sql = "SELECT user_username, text, posted_at FROM Messages JOIN User_Follows ON user_username = followed_username WHERE follower_username = followed_username;"; 

Ich denke, jetzt brauche ich eine innere Verknüpfung zu erreichen, was ich will, aber ich bin nicht sicher, ob dies richtig ist, oder wie man das macht.

Vielen Dank im Voraus.

+1

Was Sie gerade haben, ist Cross-Joins, was Ihr Problem ist. Unter keinen Umständen sollten Sie jemals implizite Joins verwenden. Sie sind eine sehr schlechte Technik und verursachen solche Probleme. Um eine Korrektur anzubieten, müssen wir die Tabellenstrukturen sehen. – HLGEM

+3

Haben Sie auf meinen Link @HLGEM – jsmith

Antwort

2

Versuchen Sie so etwas wie:

SELECT M.user_username, M.text, M.posted_at 
FROM Messages M 
INNER JOIN Users U on M.user_username= u.username 
INNER JOIN User_Follows UF on UF.followed_username = u.username 
WHERE UFfollower_username = ? 
ORDER BY posted_at DESC; 

Hinweis für zukünftige Designs, die ein langes varchar oder nvarchar Feld eine schlechte Wahl für ein Feld ist mit Ihnen wird beitreten. Wenn das Feld ein Zeichentyp-Feld ist, unterliegt es darüber hinaus oft einer zeitlichen Änderung, was ebenfalls eine schlechte Wahl für ein Schlüsselfeld ist.

Integer Joins sind im Allgemeinen viel schneller. Es kann in Ordnung sein, wenn es Ihnen ersparen kann, einige Joins zu machen, aber im Allgemeinen ist es eine schlechte Idee.

Wenn jemand seinen Benutzernamen geändert hat (was in jedem System passiert, in dem ich jemals gearbeitet habe), müßten Sie dann alle untergeordneten Tabellen aktualisieren, die recht viele zu aktualisierende Datensätze enthalten könnten. Wenn Sie einen Ersatzschlüssel verwenden, müssen Sie nur die übergeordnete Tabelle aktualisieren.

Zusätzlich ist das Wort text ein reserviertes Wort für viele Datenbanken und es ist am besten, diese in Namensfeldern zu vermeiden.

+2

Danke, große Antwort – jsmith

-1

eine einfache Sub-Abfrage sollte es tun:

select * from messages where user_username in 
(
    select followed_username from user_follows 
    where follower_username = 'your_input_username' 
); 
+1

geschaut Ich würde dies upgraden ist Sie entfernt die SQL Antipattern von Select * – HLGEM

+2

@edlerd Gibt einen Fehler: Sie haben einen Fehler in Ihrer SQL-Syntax; Überprüfen Sie das Handbuch, das Ihrer MySQL-Server-Version für die richtige Syntax entspricht, die in der Nähe von 'IN' verwendet wird (SELECT folge_username FROM User_Folows WHERE follower_username = 'kris') ' – jsmith