2009-07-14 14 views
0

Ich benutze diese Abfrage, um eine Liste von Songs anzuzeigen und zeigen, welche Songs als Favorit von einem Benutzer angeklickt wurden.Join Abfrage zurückkehrende ungerade Ergebnisse

$query = mysql_query(
    sprintf(" 
    SELECT 
     s.*, 
     UNIX_TIMESTAMP(`date`) AS `date`, 
     f.userid as favoritehash 
    FROM 
     songs s 
    LEFT JOIN 
     favorites f 
    ON 
     f.favorite = s.id 
     AND f.userid = %s", 
    $userhash) 
); 

songs Die Tabelle ist Setup als: id artist title duration etc. etc.

favorites Die Tabelle ist Setup als: id favorite userid

Die userid ein Hash-Wert in einem Cookie gespeichert wird einen eindeutigen Benutzer zu referenzieren .

Die Abfrage funktioniert gut, aber aus irgendeinem Grund, wenn ich einen Song als Favorit in einem Browser markieren. Markieren Sie das gleiche Lied als Favorit in einem anderen Browser, um mehrere Benutzer zu simulieren. Das Lied wird zweimal angezeigt ... einmal für jedes Mal, wenn es als Favorit markiert ist, aber die Favoritenanzeige < 3 wird weiterhin korrekt angezeigt.

Irgendwelche Ideen?

Nun habe es funktioniert über remindign die sprintf() aber neugierig zu wissen, warum das ist, wenn jemand irgendwelche Ideen hat.

Antwort

1

Sie verwenden sprintf und% s (string), aber Sie werden nicht den resultierenden String-Wert in Anführungszeichen gesetzt. Wenn die Benutzer-ID eine Zeichenfolge ist, müssen Sie sie in Anführungszeichen setzen, andernfalls verwenden Sie% d anstelle von% s. Da es funktioniert, wenn Sie sprintf entfernen, scheint das das Problem zu sein.

1

Ich hatte ein ähnliches Problem, ich denke, wenn Sie die And F.Userid =% s ändern, um Where f.userid =% s es sollte es beheben ?.

+0

Ich habe tatsächlich den ganzen Sprintf Teil entfernt und es scheint perfekt zu funktionieren. – ian

0

Ich denke, Ihre ON -Klausel ist falsch.

versuchen Sie stattdessen:

ON f.favorite = s.id 
WHERE f.userid = %s 
+0

Ich brauche es AND, weil ich sicherstellen muss, dass das Lieblingselement mit dem aktuellen Song in der Songzeile UND dem aktiven Benutzer übereinstimmt? – ian

+0

nun, das ist, was das tut, soweit es mich betrifft – knittl

0

Ich glaube, dass die bisherigen Vorschläge tatsächlich die LEFT JOIN besiegen würde, so dass es als INNER JOIN zu handeln; f.userid würde manchmal NULL sein, und NULL wird immer als false verglichen.

Ich würde mit dem Inhalt der favorites Tabelle beginnen. Wenn ich Ihr Schema verstehe, möchten Sie möglicherweise einen eindeutigen Schlüssel unter favorites über favorite und userid einrichten, um sicherzustellen, dass ein bestimmter Benutzer nur jeden Song als Favorit ansehen kann. Das heißt, Sie erhalten möglicherweise doppelte Zeilen und verdoppeln daher die Ergebnisse.

+0

Nun, es ist nicht doppelte Zeilen, weil ich ein Auge auf die db, wie ich damit spielte. Sobald ich das Sprintf() entfernt habe, hat es perfekt funktioniert. Und beide IDs in beiden Tabellen sind der primäre eindeutige Schlüssel. – ian

+0

Das ist sehr seltsam. Ich nehme an, Sie haben es durch eine Kettenverkettung ersetzt? War die Ausgabe der String-Operation nach der Änderung sichtbar anders? Außerdem habe ich festgestellt, dass Ihre ID-Spalten Ihre Primärschlüssel waren, aber Sie haben auch einen natürlichen Schlüssel in Ihrer Favoriten-Tabelle, und Sie können es mit einem neuen eindeutigen Schlüssel darstellen. – WCWedin

0

Da Sie einen "linken Join" verwenden, gehe ich davon aus, dass Sie eine Liste aller Songs haben möchten und dass die Favoriten der Benutzer leicht unterscheidbar sein sollen. das heißt so etwas wie dieses:

song1 details | date | null 
song2 details | date | userhash (favorite) 
song3 details | date | null 

den folgenden Versuchen:

SELECT s.*, UNIX_TIMESTAMP(`date`) AS `date`, f.userid as favoritehash 
FROM 
    songs s 
LEFT JOIN 
    (SELECT userid, favorite FROM favorites WHERE userid = %s) f 
ON 
    f.favorite = s.id 
Verwandte Themen